• 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         LOG_INFO("NapiDataShareHelper has been deleted successfully!");
208     };
209     if (napi_wrap(env, self, proxy, finalize, nullptr, nullptr) != napi_ok) {
210         finalize(env, proxy, nullptr);
211         return nullptr;
212     }
213     return self;
214 }
215 
Napi_OpenFile(napi_env env,napi_callback_info info)216 napi_value NapiDataShareHelper::Napi_OpenFile(napi_env env, napi_callback_info info)
217 {
218     LOG_DEBUG("Start");
219     auto context = std::make_shared<ContextInfo>();
220     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
221         NAPI_ASSERT_BASE(env, argc == 2 || argc == 3, " should 2 or 3 parameters!", napi_invalid_arg);
222         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
223 
224         GetUri(env, argv[PARAM0], context->uri);
225 
226         napi_valuetype valuetype = napi_undefined;
227         napi_typeof(env, argv[PARAM1], &valuetype);
228         if (valuetype == napi_string) {
229             context->mode = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
230         } else {
231             LOG_ERROR("wrong type, should be napi_string");
232         }
233         return napi_ok;
234     };
235     auto output = [context](napi_env env, napi_value *result) -> napi_status {
236         napi_create_int32(env, context->resultNumber, result);
237         return napi_ok;
238     };
239     auto exec = [context](AsyncCall::Context *ctx) {
240         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
241             OHOS::Uri uri(context->uri);
242             context->resultNumber = context->proxy->datashareHelper_->OpenFile(uri, context->mode);
243             context->status = napi_ok;
244         } else {
245             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
246                       context->proxy->datashareHelper_ == nullptr, context->uri.empty());
247         }
248     };
249     context->SetAction(std::move(input), std::move(output));
250     AsyncCall asyncCall(env, info, context);
251     return asyncCall.Call(env, exec);
252 }
253 
Napi_Insert(napi_env env,napi_callback_info info)254 napi_value NapiDataShareHelper::Napi_Insert(napi_env env, napi_callback_info info)
255 {
256     LOG_DEBUG("Start");
257     auto context = std::make_shared<ContextInfo>();
258     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
259         if (argc != 2 && argc != 3) {
260             context->error = std::make_shared<ParametersNumError>("2 or 3");
261             return napi_invalid_arg;
262         }
263         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
264 
265         if (!GetUri(env, argv[PARAM0], context->uri)) {
266             context->error = std::make_shared<ParametersTypeError>("uri", "string");
267             return napi_invalid_arg;
268         }
269 
270         context->valueBucket.Clear();
271         if (!GetValueBucketObject(context->valueBucket, env, argv[PARAM1])) {
272             context->error = std::make_shared<ParametersTypeError>("valueBucket",
273                 "[string|number|boolean|null|Uint8Array]");
274             return napi_invalid_arg;
275         }
276 
277         return napi_ok;
278     };
279     auto output = [context](napi_env env, napi_value *result) -> napi_status {
280         if (context->resultNumber < 0) {
281             context->error = std::make_shared<InnerError>();
282             return napi_generic_failure;
283         }
284         napi_create_int32(env, context->resultNumber, result);
285         return napi_ok;
286     };
287     auto exec = [context](AsyncCall::Context *ctx) {
288         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
289             OHOS::Uri uri(context->uri);
290             context->resultNumber = context->proxy->datashareHelper_->Insert(uri, context->valueBucket);
291             context->status = napi_ok;
292         } else {
293             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
294                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
295         }
296     };
297     context->SetAction(std::move(input), std::move(output));
298     AsyncCall asyncCall(env, info, context);
299     return asyncCall.Call(env, exec);
300 }
301 
Napi_Delete(napi_env env,napi_callback_info info)302 napi_value NapiDataShareHelper::Napi_Delete(napi_env env, napi_callback_info info)
303 {
304     LOG_DEBUG("Start");
305     auto context = std::make_shared<ContextInfo>();
306     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
307         if (argc != 2 && argc != 3) {
308             context->error = std::make_shared<ParametersNumError>("2 or 3");
309             return napi_invalid_arg;
310         }
311         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
312 
313         if (!GetUri(env, argv[PARAM0], context->uri)) {
314             context->error = std::make_shared<ParametersTypeError>("uri", "string");
315             return napi_invalid_arg;
316         }
317 
318         context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
319         return napi_ok;
320     };
321     auto output = [context](napi_env env, napi_value *result) -> napi_status {
322         if (context->resultNumber < 0) {
323             context->error = std::make_shared<InnerError>();
324             return napi_generic_failure;
325         }
326         napi_create_int32(env, context->resultNumber, result);
327         return napi_ok;
328     };
329     auto exec = [context](AsyncCall::Context *ctx) {
330         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
331             OHOS::Uri uri(context->uri);
332             context->resultNumber = context->proxy->datashareHelper_->Delete(uri, context->predicates);
333             context->status = napi_ok;
334         } else {
335             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
336                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
337         }
338     };
339     context->SetAction(std::move(input), std::move(output));
340     AsyncCall asyncCall(env, info, context);
341     return asyncCall.Call(env, exec);
342 }
343 
Napi_Query(napi_env env,napi_callback_info info)344 napi_value NapiDataShareHelper::Napi_Query(napi_env env, napi_callback_info info)
345 {
346     LOG_DEBUG("Start");
347     auto context = std::make_shared<ContextInfo>();
348     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
349         if (argc != 3 && argc != 4) {
350             context->error = std::make_shared<ParametersNumError>("3 or 4");
351             return napi_invalid_arg;
352         }
353         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
354 
355         if (!GetUri(env, argv[PARAM0], context->uri)) {
356             context->error = std::make_shared<ParametersTypeError>("uri", "string");
357             return napi_invalid_arg;
358         }
359 
360         context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
361 
362         context->columns = DataShareJSUtils::Convert2StrVector(env, argv[PARAM2], DataShareJSUtils::DEFAULT_BUF_SIZE);
363         return napi_ok;
364     };
365     auto output = [context](napi_env env, napi_value *result) -> napi_status {
366         if (context->resultObject == nullptr) {
367             context->error = std::make_shared<InnerError>();
368             return napi_generic_failure;
369         }
370         *result = DataShareResultSetProxy::NewInstance(env, context->resultObject);
371         return napi_ok;
372     };
373     auto exec = [context](AsyncCall::Context *ctx) {
374         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
375             OHOS::Uri uri(context->uri);
376             context->resultObject = context->proxy->datashareHelper_->Query(uri, context->predicates, context->columns);
377             context->status = napi_ok;
378         } else {
379             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
380                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
381         }
382     };
383     context->SetAction(std::move(input), std::move(output));
384     AsyncCall asyncCall(env, info, context);
385     return asyncCall.Call(env, exec);
386 }
387 
Napi_Update(napi_env env,napi_callback_info info)388 napi_value NapiDataShareHelper::Napi_Update(napi_env env, napi_callback_info info)
389 {
390     LOG_DEBUG("Start");
391     auto context = std::make_shared<ContextInfo>();
392     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
393         if (argc != 3 && argc != 4) {
394             context->error = std::make_shared<ParametersNumError>("3 or 4");
395             return napi_invalid_arg;
396         }
397         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
398 
399         if (!GetUri(env, argv[PARAM0], context->uri)) {
400             context->error = std::make_shared<ParametersTypeError>("uri", "string");
401             return napi_invalid_arg;
402         }
403 
404         context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
405 
406         context->valueBucket.Clear();
407         if (!GetValueBucketObject(context->valueBucket, env, argv[PARAM2])) {
408             context->error = std::make_shared<ParametersTypeError>("valueBucket",
409                 "[string|number|boolean|null|Uint8Array]");
410             return napi_invalid_arg;
411         }
412         return napi_ok;
413     };
414     auto output = [context](napi_env env, napi_value *result) -> napi_status {
415         if (context->resultNumber < 0) {
416             context->error = std::make_shared<InnerError>();
417             return napi_generic_failure;
418         }
419         napi_create_int32(env, context->resultNumber, result);
420         return napi_ok;
421     };
422     auto exec = [context](AsyncCall::Context *ctx) {
423         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
424             OHOS::Uri uri(context->uri);
425             context->resultNumber =
426                 context->proxy->datashareHelper_->Update(uri, context->predicates, context->valueBucket);
427             context->status = napi_ok;
428         } else {
429             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
430                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
431         }
432     };
433     context->SetAction(std::move(input), std::move(output));
434     AsyncCall asyncCall(env, info, context);
435     return asyncCall.Call(env, exec);
436 }
437 
Napi_BatchInsert(napi_env env,napi_callback_info info)438 napi_value NapiDataShareHelper::Napi_BatchInsert(napi_env env, napi_callback_info info)
439 {
440     LOG_DEBUG("Start");
441     auto context = std::make_shared<ContextInfo>();
442     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
443         if (argc != 2 && argc != 3) {
444             context->error = std::make_shared<ParametersNumError>("2 or 3");
445             return napi_invalid_arg;
446         }
447         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
448 
449         if (!GetUri(env, argv[PARAM0], context->uri)) {
450             context->error = std::make_shared<ParametersTypeError>("uri", "string");
451             return napi_invalid_arg;
452         }
453         bool status = false;
454         context->values = GetValuesBucketArray(env, argv[PARAM1], status);
455         if (!status) {
456             context->error = std::make_shared<ParametersTypeError>("valueBucket",
457                 "[string|number|boolean|null|Uint8Array]");
458             return napi_invalid_arg;
459         }
460         return napi_ok;
461     };
462     auto output = [context](napi_env env, napi_value *result) -> napi_status {
463         if (context->resultNumber < 0) {
464             context->error = std::make_shared<InnerError>();
465             return napi_generic_failure;
466         }
467         napi_create_int32(env, context->resultNumber, result);
468         return napi_ok;
469     };
470     auto exec = [context](AsyncCall::Context *ctx) {
471         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
472             OHOS::Uri uri(context->uri);
473             context->resultNumber = context->proxy->datashareHelper_->BatchInsert(uri, context->values);
474             context->status = napi_ok;
475         } else {
476             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
477                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
478         }
479     };
480     context->SetAction(std::move(input), std::move(output));
481     AsyncCall asyncCall(env, info, context);
482     return asyncCall.Call(env, exec);
483 }
484 
Napi_GetType(napi_env env,napi_callback_info info)485 napi_value NapiDataShareHelper::Napi_GetType(napi_env env, napi_callback_info info)
486 {
487     LOG_DEBUG("Start");
488     auto context = std::make_shared<ContextInfo>();
489     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
490         NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
491         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
492 
493         GetUri(env, argv[PARAM0], context->uri);
494         return napi_ok;
495     };
496     auto output = [context](napi_env env, napi_value *result) -> napi_status {
497         napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
498         return napi_ok;
499     };
500     auto exec = [context](AsyncCall::Context *ctx) {
501         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
502             OHOS::Uri uri(context->uri);
503             context->resultString = context->proxy->datashareHelper_->GetType(uri);
504             context->status = napi_ok;
505         } else {
506             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
507                       context->proxy->datashareHelper_ == nullptr, context->uri.empty());
508         }
509     };
510     context->SetAction(std::move(input), std::move(output));
511     AsyncCall asyncCall(env, info, context);
512     return asyncCall.Call(env, exec);
513 }
514 
Napi_GetFileTypes(napi_env env,napi_callback_info info)515 napi_value NapiDataShareHelper::Napi_GetFileTypes(napi_env env, napi_callback_info info)
516 {
517     LOG_DEBUG("Start");
518     auto context = std::make_shared<ContextInfo>();
519     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
520         NAPI_ASSERT_BASE(env, argc == 2 || argc == 3, " should 2 or 3 parameters!", napi_invalid_arg);
521         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
522 
523         GetUri(env, argv[PARAM0], context->uri);
524 
525         napi_valuetype valuetype = napi_undefined;
526         napi_typeof(env, argv[PARAM1], &valuetype);
527         if (valuetype == napi_string) {
528             context->mimeTypeFilter = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
529         } else {
530             LOG_ERROR("wrong type, should be napi_string");
531         }
532         return napi_ok;
533     };
534     auto output = [context](napi_env env, napi_value *result) -> napi_status {
535         *result = DataShareJSUtils::Convert2JSValue(env, context->resultStrArr);
536         return napi_ok;
537     };
538     auto exec = [context](AsyncCall::Context *ctx) {
539         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
540             OHOS::Uri uri(context->uri);
541             context->resultStrArr = context->proxy->datashareHelper_->GetFileTypes(uri, context->mimeTypeFilter);
542             context->status = napi_ok;
543         } else {
544             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
545                       context->proxy->datashareHelper_ == nullptr, context->uri.empty());
546         }
547     };
548     context->SetAction(std::move(input), std::move(output));
549     AsyncCall asyncCall(env, info, context);
550     return asyncCall.Call(env, exec);
551 }
552 
Napi_NormalizeUri(napi_env env,napi_callback_info info)553 napi_value NapiDataShareHelper::Napi_NormalizeUri(napi_env env, napi_callback_info info)
554 {
555     LOG_DEBUG("Start");
556     auto context = std::make_shared<ContextInfo>();
557     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
558         NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
559         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
560 
561         GetUri(env, argv[PARAM0], context->uri);
562         return napi_ok;
563     };
564     auto output = [context](napi_env env, napi_value *result) -> napi_status {
565         napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
566         return napi_ok;
567     };
568     auto exec = [context](AsyncCall::Context *ctx) {
569         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
570             OHOS::Uri uri(context->uri);
571             Uri uriValue = context->proxy->datashareHelper_->NormalizeUri(uri);
572             context->resultString = uriValue.ToString();
573             context->status = napi_ok;
574         } else {
575             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
576                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
577         }
578     };
579     context->SetAction(std::move(input), std::move(output));
580     AsyncCall asyncCall(env, info, context);
581     return asyncCall.Call(env, exec);
582 }
583 
Napi_DenormalizeUri(napi_env env,napi_callback_info info)584 napi_value NapiDataShareHelper::Napi_DenormalizeUri(napi_env env, napi_callback_info info)
585 {
586     LOG_DEBUG("Start");
587     auto context = std::make_shared<ContextInfo>();
588     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
589         NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
590         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
591 
592         GetUri(env, argv[PARAM0], context->uri);
593         return napi_ok;
594     };
595     auto output = [context](napi_env env, napi_value *result) -> napi_status {
596         napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
597         return napi_ok;
598     };
599     auto exec = [context](AsyncCall::Context *ctx) {
600         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
601             OHOS::Uri uri(context->uri);
602             Uri uriValue = context->proxy->datashareHelper_->DenormalizeUri(uri);
603             context->resultString = uriValue.ToString();
604             context->status = napi_ok;
605         } else {
606             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
607                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
608         }
609     };
610     context->SetAction(std::move(input), std::move(output));
611     AsyncCall asyncCall(env, info, context);
612     return asyncCall.Call(env, exec);
613 }
614 
Napi_NotifyChange(napi_env env,napi_callback_info info)615 napi_value NapiDataShareHelper::Napi_NotifyChange(napi_env env, napi_callback_info info)
616 {
617     LOG_DEBUG("Start");
618     auto context = std::make_shared<ContextInfo>();
619     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
620         NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
621         LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
622 
623         GetUri(env, argv[PARAM0], context->uri);
624         return napi_ok;
625     };
626     auto output = [context](napi_env env, napi_value *result) -> napi_status {
627         napi_get_null(env, result);
628         return napi_ok;
629     };
630     auto exec = [context](AsyncCall::Context *ctx) {
631         if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
632             OHOS::Uri uri(context->uri);
633             context->proxy->datashareHelper_->NotifyChange(uri);
634             context->status = napi_ok;
635         } else {
636             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
637                 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
638         }
639     };
640     context->SetAction(std::move(input), std::move(output));
641     AsyncCall asyncCall(env, info, context);
642     return asyncCall.Call(env, exec);
643 }
644 
Napi_On(napi_env env,napi_callback_info info)645 napi_value NapiDataShareHelper::Napi_On(napi_env env, napi_callback_info info)
646 {
647     LOG_DEBUG("Start");
648     napi_value self = nullptr;
649     size_t argc = MAX_ARGC;
650     napi_value argv[MAX_ARGC] = {nullptr};
651     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
652     NAPI_ASSERT(env, argc == ARGS_THREE, "wrong count of args");
653 
654     NapiDataShareHelper *proxy = nullptr;
655     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), nullptr);
656     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
657     NAPI_ASSERT_BASE(env, proxy->datashareHelper_ != nullptr, "there is no DataShareHelper instance", nullptr);
658 
659     napi_valuetype valueType;
660     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
661     if (valueType != napi_string) {
662         LOG_ERROR("type is not string");
663         return nullptr;
664     }
665     std::string type = DataShareJSUtils::Convert2String(env, argv[PARAM0]);
666     if (type != "dataChange") {
667         LOG_ERROR("wrong register type : %{public}s", type.c_str());
668         return nullptr;
669     }
670 
671     NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType));
672     NAPI_ASSERT_BASE(env, valueType == napi_string, "uri is not string", nullptr);
673     std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
674 
675     NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
676     NAPI_ASSERT_BASE(env, valueType == napi_function, "callback is not a function", nullptr);
677 
678     proxy->RegisteredObserver(env, uri, argv[PARAM2]);
679     return nullptr;
680 }
681 
Napi_Off(napi_env env,napi_callback_info info)682 napi_value NapiDataShareHelper::Napi_Off(napi_env env, napi_callback_info info)
683 {
684     LOG_DEBUG("Start");
685     napi_value self = nullptr;
686     size_t argc = MAX_ARGC;
687     napi_value argv[MAX_ARGC] = {nullptr};
688     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
689     NAPI_ASSERT(env, argc == ARGS_TWO || argc == ARGS_THREE, "wrong count of args");
690 
691     NapiDataShareHelper *proxy = nullptr;
692     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), nullptr);
693     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
694     NAPI_ASSERT_BASE(env, proxy->datashareHelper_ != nullptr, "there is no DataShareHelper instance", nullptr);
695 
696     napi_valuetype valueType;
697     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
698     if (valueType != napi_string) {
699         LOG_ERROR("type is not string");
700         return nullptr;
701     }
702     std::string type = DataShareJSUtils::Convert2String(env, argv[PARAM0]);
703     if (type != "dataChange") {
704         LOG_ERROR("wrong register type : %{public}s", type.c_str());
705         return nullptr;
706     }
707 
708     NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType));
709     NAPI_ASSERT_BASE(env, valueType == napi_string, "uri is not string", nullptr);
710     std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
711 
712     if (argc == ARGS_THREE) {
713         NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
714         NAPI_ASSERT_BASE(env, valueType == napi_function, "callback is not a function", nullptr);
715         proxy->UnRegisteredObserver(env, uri, argv[PARAM2]);
716         return nullptr;
717     }
718     proxy->UnRegisteredObserver(env, uri);
719     return nullptr;
720 }
721 
HasRegisteredObserver(napi_env env,std::list<sptr<NAPIDataShareObserver>> & list,napi_value callback)722 bool NapiDataShareHelper::HasRegisteredObserver(napi_env env, std::list<sptr<NAPIDataShareObserver>> &list,
723     napi_value callback)
724 {
725     for (auto &it : list) {
726         if (DataShareJSUtils::Equals(env, callback, it->observer_->GetCallback())) {
727             LOG_DEBUG("The observer has already subscribed.");
728             return true;
729         }
730     }
731     return false;
732 }
733 
RegisteredObserver(napi_env env,const std::string & uri,napi_value callback)734 void NapiDataShareHelper::RegisteredObserver(napi_env env, const std::string &uri, napi_value callback)
735 {
736     std::lock_guard<std::mutex> lck(listMutex_);
737     observerMap_.try_emplace(uri);
738 
739     auto &list = observerMap_.find(uri)->second;
740     if (HasRegisteredObserver(env, list, callback)) {
741         LOG_DEBUG("has registered observer");
742         return;
743     }
744     auto innerObserver = std::make_shared<NAPIInnerObserver>(env, callback);
745     sptr<NAPIDataShareObserver> observer(new (std::nothrow) NAPIDataShareObserver(innerObserver));
746     if (observer == nullptr) {
747         LOG_ERROR("observer is nullptr");
748         return;
749     }
750     datashareHelper_->RegisterObserver(Uri(uri), observer);
751     list.push_back(observer);
752 }
753 
UnRegisteredObserver(napi_env env,const std::string & uri,napi_value callback)754 void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string &uri, napi_value callback)
755 {
756     std::lock_guard<std::mutex> lck(listMutex_);
757     auto obs = observerMap_.find(uri);
758     if (obs == observerMap_.end()) {
759         LOG_DEBUG("this uri hasn't been registered");
760         return;
761     }
762     auto &list = obs->second;
763     auto it = list.begin();
764     while (it != list.end()) {
765         if (!DataShareJSUtils::Equals(env, callback, (*it)->observer_->GetCallback())) {
766             ++it;
767             continue;
768         }
769         datashareHelper_->UnregisterObserver(Uri(uri), *it);
770         (*it)->observer_->DeleteReference();
771         it = list.erase(it);
772         break;
773     }
774     if (list.empty()) {
775         observerMap_.erase(uri);
776     }
777 }
778 
UnRegisteredObserver(napi_env env,const std::string & uri)779 void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string &uri)
780 {
781     std::lock_guard<std::mutex> lck(listMutex_);
782     auto obs = observerMap_.find(uri);
783     if (obs == observerMap_.end()) {
784         LOG_DEBUG("this uri hasn't been registered");
785         return;
786     }
787     auto &list = obs->second;
788     auto it = list.begin();
789     while (it != list.end()) {
790         datashareHelper_->UnregisterObserver(Uri(uri), *it);
791         (*it)->observer_->DeleteReference();
792         it = list.erase(it);
793     }
794     observerMap_.erase(uri);
795 }
796 }  // namespace DataShare
797 }  // namespace OHOS