• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "napi_datashare_helper.h"
17 
18 #include "napi_common_util.h"
19 #include "datashare_helper.h"
20 #include "datashare_log.h"
21 #include "napi_base_context.h"
22 #include "napi_datashare_values_bucket.h"
23 #include "datashare_predicates_proxy.h"
24 #include "datashare_result_set_proxy.h"
25 
26 using namespace OHOS::AAFwk;
27 using namespace OHOS::AppExecFwk;
28 
29 namespace OHOS {
30 namespace DataShare {
31 constexpr int MAX_ARGC = 6;
32 
UnwrapDataSharePredicates(napi_env env,napi_value value)33 static DataSharePredicates UnwrapDataSharePredicates(napi_env env, napi_value value)
34 {
35     auto predicates = DataSharePredicatesProxy::GetNativePredicates(env, value);
36     if (predicates == nullptr) {
37         LOG_ERROR("GetNativePredicates is nullptr.");
38         return {};
39     }
40     return DataSharePredicates(predicates->GetOperationList());
41 }
42 
UnwrapValuesBucketArrayFromJS(napi_env env,napi_value param,std::vector<DataShareValuesBucket> & value)43 static bool UnwrapValuesBucketArrayFromJS(napi_env env, napi_value param,
44     std::vector<DataShareValuesBucket> &value)
45 {
46     LOG_DEBUG("Start");
47     uint32_t arraySize = 0;
48     napi_value jsValue = nullptr;
49     std::string strValue = "";
50 
51     if (!IsArrayForNapiValue(env, param, arraySize)) {
52         LOG_ERROR("IsArrayForNapiValue is false");
53         return false;
54     }
55 
56     value.clear();
57     for (uint32_t i = 0; i < arraySize; i++) {
58         jsValue = nullptr;
59         if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
60             LOG_ERROR("napi_get_element is false");
61             return false;
62         }
63 
64         DataShareValuesBucket valueBucket;
65         valueBucket.Clear();
66         if (!GetValueBucketObject(valueBucket, env, jsValue)) {
67             return false;
68         }
69 
70         value.push_back(valueBucket);
71     }
72     return true;
73 }
74 
GetValuesBucketArray(napi_env env,napi_value param,bool & status)75 static std::vector<DataShareValuesBucket> GetValuesBucketArray(napi_env env, napi_value param, bool &status)
76 {
77     LOG_DEBUG("Start");
78     std::vector<DataShareValuesBucket> result;
79     status = UnwrapValuesBucketArrayFromJS(env, param, result);
80     return result;
81 }
82 
GetUri(napi_env env,napi_value jsValue,std::string & uri)83 static bool GetUri(napi_env env, napi_value jsValue, std::string &uri)
84 {
85     LOG_DEBUG("Start");
86     napi_valuetype valuetype = napi_undefined;
87     napi_typeof(env, jsValue, &valuetype);
88     if (valuetype != napi_string) {
89         return false;
90     }
91     uri = DataShareJSUtils::Convert2String(env, jsValue);
92     return true;
93 }
94 
Napi_CreateDataShareHelper(napi_env env,napi_callback_info info)95 napi_value NapiDataShareHelper::Napi_CreateDataShareHelper(napi_env env, napi_callback_info info)
96 {
97     LOG_DEBUG("Start");
98     auto ctxInfo = std::make_shared<CreateContextInfo>();
99     auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
100         if (argc != 2 && argc != 3) {
101             ctxInfo->error = std::make_shared<ParametersNumError>("2 or 3");
102             return napi_invalid_arg;
103         }
104         bool isStageMode = false;
105         napi_status status = AbilityRuntime::IsStageContext(env, argv[PARAM0], isStageMode);
106         if (status != napi_ok || !isStageMode) {
107             ctxInfo->isStageMode = false;
108             auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
109             if (!GetUri(env, argv[PARAM0], ctxInfo->strUri)) {
110                 ctxInfo->error = std::make_shared<ParametersTypeError>("uri", "string");
111                 return napi_invalid_arg;
112             }
113 
114             if (ability == nullptr) {
115                 ctxInfo->error = std::make_shared<ParametersTypeError>("ability", "not nullptr");
116                 return napi_invalid_arg;
117             }
118             ctxInfo->contextF = ability->GetContext();
119         } else {
120             ctxInfo->contextS = OHOS::AbilityRuntime::GetStageModeContext(env, argv[PARAM0]);
121             if (!GetUri(env, argv[PARAM1], ctxInfo->strUri)) {
122                 ctxInfo->error = std::make_shared<ParametersTypeError>("uri", "string");
123                 return napi_invalid_arg;
124             }
125 
126             if (ctxInfo->contextS == nullptr) {
127                 ctxInfo->error = std::make_shared<ParametersTypeError>("contextS", "not nullptr");
128                 return napi_invalid_arg;
129             }
130         }
131 
132         napi_value helperProxy = nullptr;
133         status = napi_new_instance(env, GetConstructor(env), argc, argv, &helperProxy);
134         if ((helperProxy == nullptr) || (status != napi_ok)) {
135             ctxInfo->error = std::make_shared<DataShareHelperInitError>();
136             return napi_generic_failure;
137         }
138         napi_create_reference(env, helperProxy, 1, &(ctxInfo->ref));
139         ctxInfo->env = env;
140         return napi_ok;
141     };
142     auto output = [ctxInfo](napi_env env, napi_value *result) -> napi_status {
143         if (ctxInfo->dataShareHelper == nullptr) {
144             ctxInfo->error = std::make_shared<DataShareHelperInitError>();
145             return napi_generic_failure;
146         }
147         napi_status status = napi_get_reference_value(env, ctxInfo->ref, result);
148         NapiDataShareHelper *proxy = nullptr;
149         status = napi_unwrap(env, *result, reinterpret_cast<void **>(&proxy));
150         if (proxy == nullptr) {
151             LOG_ERROR("proxy is nullptr");
152             return status;
153         }
154         proxy->datashareHelper_ = std::move(ctxInfo->dataShareHelper);
155         return status;
156     };
157     auto exec = [ctxInfo](AsyncCall::Context *ctx) {
158         if (ctxInfo->isStageMode && ctxInfo->contextS != nullptr) {
159             ctxInfo->dataShareHelper = DataShareHelper::Creator(ctxInfo->contextS, ctxInfo->strUri);
160         } else if (!ctxInfo->isStageMode && ctxInfo->contextF != nullptr) {
161             ctxInfo->dataShareHelper = DataShareHelper::Creator(ctxInfo->contextF, ctxInfo->strUri);
162         }
163     };
164     ctxInfo->SetAction(std::move(input), std::move(output));
165     AsyncCall asyncCall(env, info, ctxInfo);
166     return asyncCall.Call(env, exec);
167 }
168 
GetConstructor(napi_env env)169 napi_value NapiDataShareHelper::GetConstructor(napi_env env)
170 {
171     napi_value cons = nullptr;
172     napi_property_descriptor clzDes[] = {
173         DECLARE_NAPI_FUNCTION("on", Napi_On),
174         DECLARE_NAPI_FUNCTION("off", Napi_Off),
175         DECLARE_NAPI_FUNCTION("insert", Napi_Insert),
176         DECLARE_NAPI_FUNCTION("delete", Napi_Delete),
177         DECLARE_NAPI_FUNCTION("query", Napi_Query),
178         DECLARE_NAPI_FUNCTION("update", Napi_Update),
179         DECLARE_NAPI_FUNCTION("batchInsert", Napi_BatchInsert),
180         DECLARE_NAPI_FUNCTION("normalizeUri", Napi_NormalizeUri),
181         DECLARE_NAPI_FUNCTION("denormalizeUri", Napi_DenormalizeUri),
182         DECLARE_NAPI_FUNCTION("notifyChange", Napi_NotifyChange),
183     };
184     NAPI_CALL(env, napi_define_class(env, "DataShareHelper", NAPI_AUTO_LENGTH, Initialize, nullptr,
185         sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons));
186     return cons;
187 }
188 
Initialize(napi_env env,napi_callback_info info)189 napi_value NapiDataShareHelper::Initialize(napi_env env, napi_callback_info info)
190 {
191     LOG_DEBUG("Start");
192     napi_value self = nullptr;
193     size_t argc = ARGS_MAX_COUNT;
194     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
195     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
196     if (argc <= 1) {
197         LOG_ERROR("Parameters error, need at least 2 parameters!");
198         return nullptr;
199     }
200     auto *proxy = new (std::nothrow) NapiDataShareHelper();
201     if (proxy == nullptr) {
202         return nullptr;
203     }
204     auto finalize = [](napi_env env, void * data, void * hint) {
205         NapiDataShareHelper *proxy = reinterpret_cast<NapiDataShareHelper *>(data);
206         delete proxy;
207     };
208     if (napi_wrap(env, self, proxy, finalize, nullptr, nullptr) != napi_ok) {
209         finalize(env, proxy, nullptr);
210         return nullptr;
211     }
212     return self;
213 }
214 
Napi_OpenFile(napi_env env,napi_callback_info info)215 napi_value NapiDataShareHelper::Napi_OpenFile(napi_env env, napi_callback_info info)
216 {
217     LOG_DEBUG("Start");
218     auto context = std::make_shared<ContextInfo>();
219     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
220         NAPI_ASSERT_BASE(env, argc == 2 || argc == 3, " should 2 or 3 parameters!", napi_invalid_arg);
221         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
222 
223         GetUri(env, argv[PARAM0], context->uri);
224 
225         napi_valuetype valuetype = napi_undefined;
226         napi_typeof(env, argv[PARAM1], &valuetype);
227         if (valuetype == napi_string) {
228             context->mode = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
229         } else {
230             LOG_ERROR("wrong type, should be napi_string");
231         }
232         return napi_ok;
233     };
234     auto output = [context](napi_env env, napi_value *result) -> napi_status {
235         napi_create_int32(env, context->resultNumber, result);
236         return napi_ok;
237     };
238     auto exec = [context](AsyncCall::Context *ctx) {
239         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
240             OHOS::Uri uri(context->uri);
241             context->resultNumber = context->proxy->datashareHelper_->OpenFile(uri, context->mode);
242             context->status = napi_ok;
243         } else {
244             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
245                       context->proxy->datashareHelper_ == nullptr, context->uri.empty());
246         }
247     };
248     context->SetAction(std::move(input), std::move(output));
249     AsyncCall asyncCall(env, info, context);
250     return asyncCall.Call(env, exec);
251 }
252 
Napi_Insert(napi_env env,napi_callback_info info)253 napi_value NapiDataShareHelper::Napi_Insert(napi_env env, napi_callback_info info)
254 {
255     LOG_DEBUG("Start");
256     auto context = std::make_shared<ContextInfo>();
257     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
258         if (argc != 2 && argc != 3) {
259             context->error = std::make_shared<ParametersNumError>("2 or 3");
260             return napi_invalid_arg;
261         }
262         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
263 
264         if (!GetUri(env, argv[PARAM0], context->uri)) {
265             context->error = std::make_shared<ParametersTypeError>("uri", "string");
266             return napi_invalid_arg;
267         }
268 
269         context->valueBucket.Clear();
270         if (!GetValueBucketObject(context->valueBucket, env, argv[PARAM1])) {
271             context->error = std::make_shared<ParametersTypeError>("valueBucket",
272                 "[string|number|boolean|null|Uint8Array]");
273             return napi_invalid_arg;
274         }
275 
276         return napi_ok;
277     };
278     auto output = [context](napi_env env, napi_value *result) -> napi_status {
279         if (context->resultNumber < 0) {
280             context->error = std::make_shared<InnerError>();
281             return napi_generic_failure;
282         }
283         napi_create_int32(env, context->resultNumber, result);
284         return napi_ok;
285     };
286     auto exec = [context](AsyncCall::Context *ctx) {
287         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
288             OHOS::Uri uri(context->uri);
289             context->resultNumber = context->proxy->datashareHelper_->Insert(uri, context->valueBucket);
290             context->status = napi_ok;
291         } else {
292             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
293                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
294         }
295     };
296     context->SetAction(std::move(input), std::move(output));
297     AsyncCall asyncCall(env, info, context);
298     return asyncCall.Call(env, exec);
299 }
300 
Napi_Delete(napi_env env,napi_callback_info info)301 napi_value NapiDataShareHelper::Napi_Delete(napi_env env, napi_callback_info info)
302 {
303     LOG_DEBUG("Start");
304     auto context = std::make_shared<ContextInfo>();
305     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
306         if (argc != 2 && argc != 3) {
307             context->error = std::make_shared<ParametersNumError>("2 or 3");
308             return napi_invalid_arg;
309         }
310         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
311 
312         if (!GetUri(env, argv[PARAM0], context->uri)) {
313             context->error = std::make_shared<ParametersTypeError>("uri", "string");
314             return napi_invalid_arg;
315         }
316 
317         context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
318         return napi_ok;
319     };
320     auto output = [context](napi_env env, napi_value *result) -> napi_status {
321         if (context->resultNumber < 0) {
322             context->error = std::make_shared<InnerError>();
323             return napi_generic_failure;
324         }
325         napi_create_int32(env, context->resultNumber, result);
326         return napi_ok;
327     };
328     auto exec = [context](AsyncCall::Context *ctx) {
329         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
330             OHOS::Uri uri(context->uri);
331             context->resultNumber = context->proxy->datashareHelper_->Delete(uri, context->predicates);
332             context->status = napi_ok;
333         } else {
334             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
335                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
336         }
337     };
338     context->SetAction(std::move(input), std::move(output));
339     AsyncCall asyncCall(env, info, context);
340     return asyncCall.Call(env, exec);
341 }
342 
Napi_Query(napi_env env,napi_callback_info info)343 napi_value NapiDataShareHelper::Napi_Query(napi_env env, napi_callback_info info)
344 {
345     LOG_DEBUG("Start");
346     auto context = std::make_shared<ContextInfo>();
347     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
348         if (argc != 3 && argc != 4) {
349             context->error = std::make_shared<ParametersNumError>("3 or 4");
350             return napi_invalid_arg;
351         }
352         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
353 
354         if (!GetUri(env, argv[PARAM0], context->uri)) {
355             context->error = std::make_shared<ParametersTypeError>("uri", "string");
356             return napi_invalid_arg;
357         }
358 
359         context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
360 
361         context->columns = DataShareJSUtils::Convert2StrVector(env, argv[PARAM2], DataShareJSUtils::DEFAULT_BUF_SIZE);
362         return napi_ok;
363     };
364     auto output = [context](napi_env env, napi_value *result) -> napi_status {
365         if (context->resultObject == nullptr) {
366             context->error = std::make_shared<InnerError>();
367             return napi_generic_failure;
368         }
369         *result = DataShareResultSetProxy::NewInstance(env, context->resultObject);
370         return napi_ok;
371     };
372     auto exec = [context](AsyncCall::Context *ctx) {
373         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
374             OHOS::Uri uri(context->uri);
375             context->resultObject = context->proxy->datashareHelper_->Query(uri, context->predicates, context->columns);
376             context->status = napi_ok;
377         } else {
378             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
379                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
380         }
381     };
382     context->SetAction(std::move(input), std::move(output));
383     AsyncCall asyncCall(env, info, context);
384     return asyncCall.Call(env, exec);
385 }
386 
Napi_Update(napi_env env,napi_callback_info info)387 napi_value NapiDataShareHelper::Napi_Update(napi_env env, napi_callback_info info)
388 {
389     LOG_DEBUG("Start");
390     auto context = std::make_shared<ContextInfo>();
391     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
392         if (argc != 3 && argc != 4) {
393             context->error = std::make_shared<ParametersNumError>("3 or 4");
394             return napi_invalid_arg;
395         }
396         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
397 
398         if (!GetUri(env, argv[PARAM0], context->uri)) {
399             context->error = std::make_shared<ParametersTypeError>("uri", "string");
400             return napi_invalid_arg;
401         }
402 
403         context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
404 
405         context->valueBucket.Clear();
406         if (!GetValueBucketObject(context->valueBucket, env, argv[PARAM2])) {
407             context->error = std::make_shared<ParametersTypeError>("valueBucket",
408                 "[string|number|boolean|null|Uint8Array]");
409             return napi_invalid_arg;
410         }
411         return napi_ok;
412     };
413     auto output = [context](napi_env env, napi_value *result) -> napi_status {
414         if (context->resultNumber < 0) {
415             context->error = std::make_shared<InnerError>();
416             return napi_generic_failure;
417         }
418         napi_create_int32(env, context->resultNumber, result);
419         return napi_ok;
420     };
421     auto exec = [context](AsyncCall::Context *ctx) {
422         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
423             OHOS::Uri uri(context->uri);
424             context->resultNumber =
425                 context->proxy->datashareHelper_->Update(uri, context->predicates, context->valueBucket);
426             context->status = napi_ok;
427         } else {
428             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
429                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
430         }
431     };
432     context->SetAction(std::move(input), std::move(output));
433     AsyncCall asyncCall(env, info, context);
434     return asyncCall.Call(env, exec);
435 }
436 
Napi_BatchInsert(napi_env env,napi_callback_info info)437 napi_value NapiDataShareHelper::Napi_BatchInsert(napi_env env, napi_callback_info info)
438 {
439     LOG_DEBUG("Start");
440     auto context = std::make_shared<ContextInfo>();
441     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
442         if (argc != 2 && argc != 3) {
443             context->error = std::make_shared<ParametersNumError>("2 or 3");
444             return napi_invalid_arg;
445         }
446         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
447 
448         if (!GetUri(env, argv[PARAM0], context->uri)) {
449             context->error = std::make_shared<ParametersTypeError>("uri", "string");
450             return napi_invalid_arg;
451         }
452         bool status = false;
453         context->values = GetValuesBucketArray(env, argv[PARAM1], status);
454         if (!status) {
455             context->error = std::make_shared<ParametersTypeError>("valueBucket",
456                 "[string|number|boolean|null|Uint8Array]");
457             return napi_invalid_arg;
458         }
459         return napi_ok;
460     };
461     auto output = [context](napi_env env, napi_value *result) -> napi_status {
462         if (context->resultNumber < 0) {
463             context->error = std::make_shared<InnerError>();
464             return napi_generic_failure;
465         }
466         napi_create_int32(env, context->resultNumber, result);
467         return napi_ok;
468     };
469     auto exec = [context](AsyncCall::Context *ctx) {
470         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
471             OHOS::Uri uri(context->uri);
472             context->resultNumber = context->proxy->datashareHelper_->BatchInsert(uri, context->values);
473             context->status = napi_ok;
474         } else {
475             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
476                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
477         }
478     };
479     context->SetAction(std::move(input), std::move(output));
480     AsyncCall asyncCall(env, info, context);
481     return asyncCall.Call(env, exec);
482 }
483 
Napi_GetType(napi_env env,napi_callback_info info)484 napi_value NapiDataShareHelper::Napi_GetType(napi_env env, napi_callback_info info)
485 {
486     LOG_DEBUG("Start");
487     auto context = std::make_shared<ContextInfo>();
488     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
489         NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
490         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
491 
492         GetUri(env, argv[PARAM0], context->uri);
493         return napi_ok;
494     };
495     auto output = [context](napi_env env, napi_value *result) -> napi_status {
496         napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
497         return napi_ok;
498     };
499     auto exec = [context](AsyncCall::Context *ctx) {
500         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
501             OHOS::Uri uri(context->uri);
502             context->resultString = context->proxy->datashareHelper_->GetType(uri);
503             context->status = napi_ok;
504         } else {
505             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
506                       context->proxy->datashareHelper_ == nullptr, context->uri.empty());
507         }
508     };
509     context->SetAction(std::move(input), std::move(output));
510     AsyncCall asyncCall(env, info, context);
511     return asyncCall.Call(env, exec);
512 }
513 
Napi_GetFileTypes(napi_env env,napi_callback_info info)514 napi_value NapiDataShareHelper::Napi_GetFileTypes(napi_env env, napi_callback_info info)
515 {
516     LOG_DEBUG("Start");
517     auto context = std::make_shared<ContextInfo>();
518     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
519         NAPI_ASSERT_BASE(env, argc == 2 || argc == 3, " should 2 or 3 parameters!", napi_invalid_arg);
520         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
521 
522         GetUri(env, argv[PARAM0], context->uri);
523 
524         napi_valuetype valuetype = napi_undefined;
525         napi_typeof(env, argv[PARAM1], &valuetype);
526         if (valuetype == napi_string) {
527             context->mimeTypeFilter = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
528         } else {
529             LOG_ERROR("wrong type, should be napi_string");
530         }
531         return napi_ok;
532     };
533     auto output = [context](napi_env env, napi_value *result) -> napi_status {
534         *result = DataShareJSUtils::Convert2JSValue(env, context->resultStrArr);
535         return napi_ok;
536     };
537     auto exec = [context](AsyncCall::Context *ctx) {
538         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
539             OHOS::Uri uri(context->uri);
540             context->resultStrArr = context->proxy->datashareHelper_->GetFileTypes(uri, context->mimeTypeFilter);
541             context->status = napi_ok;
542         } else {
543             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
544                       context->proxy->datashareHelper_ == nullptr, context->uri.empty());
545         }
546     };
547     context->SetAction(std::move(input), std::move(output));
548     AsyncCall asyncCall(env, info, context);
549     return asyncCall.Call(env, exec);
550 }
551 
Napi_NormalizeUri(napi_env env,napi_callback_info info)552 napi_value NapiDataShareHelper::Napi_NormalizeUri(napi_env env, napi_callback_info info)
553 {
554     LOG_DEBUG("Start");
555     auto context = std::make_shared<ContextInfo>();
556     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
557         NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
558         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
559 
560         GetUri(env, argv[PARAM0], context->uri);
561         return napi_ok;
562     };
563     auto output = [context](napi_env env, napi_value *result) -> napi_status {
564         napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
565         return napi_ok;
566     };
567     auto exec = [context](AsyncCall::Context *ctx) {
568         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
569             OHOS::Uri uri(context->uri);
570             Uri uriValue = context->proxy->datashareHelper_->NormalizeUri(uri);
571             context->resultString = uriValue.ToString();
572             context->status = napi_ok;
573         } else {
574             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
575                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
576         }
577     };
578     context->SetAction(std::move(input), std::move(output));
579     AsyncCall asyncCall(env, info, context);
580     return asyncCall.Call(env, exec);
581 }
582 
Napi_DenormalizeUri(napi_env env,napi_callback_info info)583 napi_value NapiDataShareHelper::Napi_DenormalizeUri(napi_env env, napi_callback_info info)
584 {
585     LOG_DEBUG("Start");
586     auto context = std::make_shared<ContextInfo>();
587     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
588         NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
589         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
590 
591         GetUri(env, argv[PARAM0], context->uri);
592         return napi_ok;
593     };
594     auto output = [context](napi_env env, napi_value *result) -> napi_status {
595         napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
596         return napi_ok;
597     };
598     auto exec = [context](AsyncCall::Context *ctx) {
599         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
600             OHOS::Uri uri(context->uri);
601             Uri uriValue = context->proxy->datashareHelper_->DenormalizeUri(uri);
602             context->resultString = uriValue.ToString();
603             context->status = napi_ok;
604         } else {
605             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
606                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
607         }
608     };
609     context->SetAction(std::move(input), std::move(output));
610     AsyncCall asyncCall(env, info, context);
611     return asyncCall.Call(env, exec);
612 }
613 
Napi_NotifyChange(napi_env env,napi_callback_info info)614 napi_value NapiDataShareHelper::Napi_NotifyChange(napi_env env, napi_callback_info info)
615 {
616     LOG_DEBUG("Start");
617     auto context = std::make_shared<ContextInfo>();
618     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
619         NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
620         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
621 
622         GetUri(env, argv[PARAM0], context->uri);
623         return napi_ok;
624     };
625     auto output = [context](napi_env env, napi_value *result) -> napi_status {
626         napi_get_null(env, result);
627         return napi_ok;
628     };
629     auto exec = [context](AsyncCall::Context *ctx) {
630         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
631             OHOS::Uri uri(context->uri);
632             context->proxy->datashareHelper_->NotifyChange(uri);
633             context->status = napi_ok;
634         } else {
635             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
636                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
637         }
638     };
639     context->SetAction(std::move(input), std::move(output));
640     AsyncCall asyncCall(env, info, context);
641     return asyncCall.Call(env, exec);
642 }
643 
Napi_On(napi_env env,napi_callback_info info)644 napi_value NapiDataShareHelper::Napi_On(napi_env env, napi_callback_info info)
645 {
646     LOG_DEBUG("Start");
647     napi_value self = nullptr;
648     size_t argc = MAX_ARGC;
649     napi_value argv[MAX_ARGC] = {nullptr};
650     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
651     NAPI_ASSERT(env, argc == ARGS_THREE, "wrong count of args");
652 
653     NapiDataShareHelper *proxy = nullptr;
654     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), nullptr);
655     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
656     NAPI_ASSERT_BASE(env, proxy->datashareHelper_ != nullptr, "there is no DataShareHelper instance", nullptr);
657 
658     napi_valuetype valueType;
659     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
660     if (valueType != napi_string) {
661         LOG_ERROR("type is not string");
662         return nullptr;
663     }
664     std::string type = DataShareJSUtils::Convert2String(env, argv[PARAM0]);
665     if (type != "dataChange") {
666         LOG_ERROR("wrong register type : %{public}s", type.c_str());
667         return nullptr;
668     }
669 
670     NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType));
671     NAPI_ASSERT_BASE(env, valueType == napi_string, "uri is not string", nullptr);
672     std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
673 
674     NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
675     NAPI_ASSERT_BASE(env, valueType == napi_function, "callback is not a function", nullptr);
676 
677     proxy->RegisteredObserver(env, uri, argv[PARAM2]);
678     return nullptr;
679 }
680 
Napi_Off(napi_env env,napi_callback_info info)681 napi_value NapiDataShareHelper::Napi_Off(napi_env env, napi_callback_info info)
682 {
683     LOG_DEBUG("Start");
684     napi_value self = nullptr;
685     size_t argc = MAX_ARGC;
686     napi_value argv[MAX_ARGC] = {nullptr};
687     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
688     NAPI_ASSERT(env, argc == ARGS_TWO || argc == ARGS_THREE, "wrong count of args");
689 
690     NapiDataShareHelper *proxy = nullptr;
691     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), nullptr);
692     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
693     NAPI_ASSERT_BASE(env, proxy->datashareHelper_ != nullptr, "there is no DataShareHelper instance", nullptr);
694 
695     napi_valuetype valueType;
696     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
697     if (valueType != napi_string) {
698         LOG_ERROR("type is not string");
699         return nullptr;
700     }
701     std::string type = DataShareJSUtils::Convert2String(env, argv[PARAM0]);
702     if (type != "dataChange") {
703         LOG_ERROR("wrong register type : %{public}s", type.c_str());
704         return nullptr;
705     }
706 
707     NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType));
708     NAPI_ASSERT_BASE(env, valueType == napi_string, "uri is not string", nullptr);
709     std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
710 
711     if (argc == ARGS_THREE) {
712         NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
713         NAPI_ASSERT_BASE(env, valueType == napi_function, "callback is not a function", nullptr);
714         proxy->UnRegisteredObserver(env, uri, argv[PARAM2]);
715         return nullptr;
716     }
717     proxy->UnRegisteredObserver(env, uri);
718     return nullptr;
719 }
720 
HasRegisteredObserver(napi_env env,std::list<sptr<NAPIDataShareObserver>> & list,napi_value callback)721 bool NapiDataShareHelper::HasRegisteredObserver(napi_env env, std::list<sptr<NAPIDataShareObserver>> &list,
722     napi_value callback)
723 {
724     for (auto &it : list) {
725         if (DataShareJSUtils::Equals(env, callback, it->observer_->GetCallback())) {
726             LOG_DEBUG("The observer has already subscribed.");
727             return true;
728         }
729     }
730     return false;
731 }
732 
RegisteredObserver(napi_env env,const std::string & uri,napi_value callback)733 void NapiDataShareHelper::RegisteredObserver(napi_env env, const std::string &uri, napi_value callback)
734 {
735     std::lock_guard<std::mutex> lck(listMutex_);
736     observerMap_.try_emplace(uri);
737 
738     auto &list = observerMap_.find(uri)->second;
739     if (HasRegisteredObserver(env, list, callback)) {
740         LOG_DEBUG("has registered observer");
741         return;
742     }
743     auto innerObserver = std::make_shared<NAPIInnerObserver>(env, callback);
744     sptr<NAPIDataShareObserver> observer(new (std::nothrow) NAPIDataShareObserver(innerObserver));
745     if (observer == nullptr) {
746         LOG_ERROR("observer is nullptr");
747         return;
748     }
749     datashareHelper_->RegisterObserver(Uri(uri), observer);
750     list.push_back(observer);
751 }
752 
UnRegisteredObserver(napi_env env,const std::string & uri,napi_value callback)753 void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string &uri, napi_value callback)
754 {
755     std::lock_guard<std::mutex> lck(listMutex_);
756     auto obs = observerMap_.find(uri);
757     if (obs == observerMap_.end()) {
758         LOG_DEBUG("this uri hasn't been registered");
759         return;
760     }
761     auto &list = obs->second;
762     auto it = list.begin();
763     while (it != list.end()) {
764         if (!DataShareJSUtils::Equals(env, callback, (*it)->observer_->GetCallback())) {
765             ++it;
766             continue;
767         }
768         datashareHelper_->UnregisterObserver(Uri(uri), *it);
769         (*it)->observer_->DeleteReference();
770         it = list.erase(it);
771         break;
772     }
773     if (list.empty()) {
774         observerMap_.erase(uri);
775     }
776 }
777 
UnRegisteredObserver(napi_env env,const std::string & uri)778 void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string &uri)
779 {
780     std::lock_guard<std::mutex> lck(listMutex_);
781     auto obs = observerMap_.find(uri);
782     if (obs == observerMap_.end()) {
783         LOG_DEBUG("this uri hasn't been registered");
784         return;
785     }
786     auto &list = obs->second;
787     auto it = list.begin();
788     while (it != list.end()) {
789         datashareHelper_->UnregisterObserver(Uri(uri), *it);
790         (*it)->observer_->DeleteReference();
791         it = list.erase(it);
792     }
793     observerMap_.erase(uri);
794 }
795 }  // namespace DataShare
796 }  // namespace OHOS