1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_datashare_helper.h"
17 
18 #include "data_proxy_observer_stub.h"
19 #include "datashare_helper.h"
20 #include "datashare_log.h"
21 #include "datashare_predicates_proxy.h"
22 #include "datashare_result_set_proxy.h"
23 #include "datashare_valuebucket_convert.h"
24 #include "napi_base_context.h"
25 #include "napi_common_util.h"
26 #include "napi_datashare_values_bucket.h"
27 
28 using namespace OHOS::AAFwk;
29 using namespace OHOS::AppExecFwk;
30 
31 namespace OHOS {
32 namespace DataShare {
33 static constexpr int MAX_ARGC = 6;
34 static __thread napi_ref constructor_ = nullptr;
GetSilentUri(napi_env env,napi_value jsValue,std::string & uri)35 static bool GetSilentUri(napi_env env, napi_value jsValue, std::string &uri)
36 {
37     napi_valuetype valuetype = napi_undefined;
38     napi_typeof(env, jsValue, &valuetype);
39     if (valuetype == napi_undefined || valuetype == napi_null) {
40         return true;
41     }
42     if (valuetype == napi_string) {
43         uri = DataShareJSUtils::Convert2String(env, jsValue);
44         return true;
45     }
46     return false;
47 }
48 
GetUri(napi_env env,napi_value jsValue,std::string & uri)49 static bool GetUri(napi_env env, napi_value jsValue, std::string &uri)
50 {
51     napi_valuetype valuetype = napi_undefined;
52     napi_typeof(env, jsValue, &valuetype);
53     if (valuetype != napi_string) {
54         return false;
55     }
56     uri = DataShareJSUtils::Convert2String(env, jsValue);
57     return true;
58 }
59 
GetOptions(napi_env env,napi_value jsValue,CreateOptions & options)60 bool NapiDataShareHelper::GetOptions(napi_env env, napi_value jsValue, CreateOptions &options)
61 {
62     napi_valuetype type = napi_undefined;
63     napi_typeof(env, jsValue, &type);
64     if (type != napi_object) {
65         LOG_ERROR("CreateOptions is not object");
66         return false;
67     }
68     napi_value isProxyJs = nullptr;
69     napi_status status = napi_get_named_property(env, jsValue, "isProxy", &isProxyJs);
70     if (status != napi_ok) {
71         LOG_ERROR("napi_get_named_property failed %{public}d", status);
72         return false;
73     }
74     napi_typeof(env, isProxyJs, &type);
75     if (type != napi_boolean) {
76         LOG_ERROR("CreateOptions.isProxy is not bool");
77         return false;
78     }
79     status = napi_get_value_bool(env, isProxyJs, &options.isProxy_);
80     if (status != napi_ok) {
81         LOG_ERROR("napi_get_value_bool failed %{public}d", status);
82         return false;
83     }
84     options.enabled_ = true;
85     return true;
86 }
87 
Napi_CreateDataShareHelper(napi_env env,napi_callback_info info)88 napi_value NapiDataShareHelper::Napi_CreateDataShareHelper(napi_env env, napi_callback_info info)
89 {
90     auto ctxInfo = std::make_shared<CreateContextInfo>();
91     auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
92         NAPI_ASSERT_CALL_ERRCODE(env, argc == 2 || argc == 3 || argc == 4,
93             ctxInfo->error = std::make_shared<ParametersNumError>("2 or 3 or 4"), napi_invalid_arg);
94         ctxInfo->contextS = OHOS::AbilityRuntime::GetStageModeContext(env, argv[0]);
95         NAPI_ASSERT_CALL_ERRCODE(env, ctxInfo->contextS != nullptr,
96             ctxInfo->error = std::make_shared<ParametersTypeError>("contextS", "not nullptr"), napi_invalid_arg);
97         NAPI_ASSERT_CALL_ERRCODE(env, GetUri(env, argv[1], ctxInfo->strUri),
98             ctxInfo->error = std::make_shared<ParametersTypeError>("uri", "string"), napi_invalid_arg);
99         Uri uri(ctxInfo->strUri);
100         if (uri.GetScheme() == "datashareproxy") {
101             NAPI_ASSERT_CALL_ERRCODE(env, argc == 3 || argc == 4,
102                 ctxInfo->error = std::make_shared<ParametersNumError>("3 or 4"), napi_invalid_arg);
103             NAPI_ASSERT_CALL_ERRCODE(env, GetOptions(env, argv[2], ctxInfo->options),
104                 ctxInfo->error = std::make_shared<ParametersTypeError>("option", "CreateOption"), napi_invalid_arg);
105         }
106         napi_value helperProxy = nullptr;
107         napi_status status = napi_new_instance(env, GetConstructor(env), argc, argv, &helperProxy);
108         NAPI_ASSERT_CALL_ERRCODE(env, helperProxy != nullptr && status == napi_ok,
109             ctxInfo->error = std::make_shared<DataShareHelperInitError>(), napi_generic_failure);
110         napi_create_reference(env, helperProxy, 1, &(ctxInfo->ref));
111         ctxInfo->env = env;
112         return napi_ok;
113     };
114     auto output = [ctxInfo](napi_env env, napi_value *result) -> napi_status {
115         NAPI_ASSERT_CALL_ERRCODE(env, ctxInfo->dataShareHelper != nullptr,
116             ctxInfo->error = std::make_shared<DataShareHelperInitError>(), napi_generic_failure);
117         napi_status status = napi_get_reference_value(env, ctxInfo->ref, result);
118         NAPI_ASSERT_CALL_ERRCODE(env, result != nullptr,
119             ctxInfo->error = std::make_shared<DataShareHelperInitError>(), napi_generic_failure);
120         NapiDataShareHelper *proxy = nullptr;
121         status = napi_unwrap(env, *result, reinterpret_cast<void **>(&proxy));
122         NAPI_ASSERT_CALL_ERRCODE(env, proxy != nullptr, ctxInfo->error = std::make_shared<DataShareHelperInitError>(),
123             status);
124         proxy->jsRdbObsManager_ = std::make_shared<NapiRdbSubscriberManager>(ctxInfo->dataShareHelper);
125         proxy->jsPublishedObsManager_ = std::make_shared<NapiPublishedSubscriberManager>(ctxInfo->dataShareHelper);
126         proxy->SetHelper(std::move(ctxInfo->dataShareHelper));
127         return status;
128     };
129     auto exec = [ctxInfo](AsyncCall::Context *ctx) {
130         if (ctxInfo->options.enabled_) {
131             ctxInfo->options.token_ = ctxInfo->contextS->GetToken();
132             ctxInfo->dataShareHelper = DataShareHelper::Creator(ctxInfo->strUri, ctxInfo->options);
133         } else {
134             ctxInfo->dataShareHelper = DataShareHelper::Creator(ctxInfo->contextS->GetToken(), ctxInfo->strUri);
135         }
136     };
137     ctxInfo->SetAction(std::move(input), std::move(output));
138     AsyncCall asyncCall(env, info, ctxInfo);
139     return asyncCall.Call(env, exec);
140 }
141 
GetConstructor(napi_env env)142 napi_value NapiDataShareHelper::GetConstructor(napi_env env)
143 {
144     napi_value cons = nullptr;
145     if (constructor_ != nullptr) {
146         napi_get_reference_value(env, constructor_, &cons);
147         return cons;
148     }
149     napi_property_descriptor clzDes[] = {
150         DECLARE_NAPI_FUNCTION("on", Napi_On),
151         DECLARE_NAPI_FUNCTION("off", Napi_Off),
152         DECLARE_NAPI_FUNCTION("insert", Napi_Insert),
153         DECLARE_NAPI_FUNCTION("delete", Napi_Delete),
154         DECLARE_NAPI_FUNCTION("query", Napi_Query),
155         DECLARE_NAPI_FUNCTION("update", Napi_Update),
156         DECLARE_NAPI_FUNCTION("batchInsert", Napi_BatchInsert),
157         DECLARE_NAPI_FUNCTION("batchUpdate", Napi_BatchUpdate),
158         DECLARE_NAPI_FUNCTION("normalizeUri", Napi_NormalizeUri),
159         DECLARE_NAPI_FUNCTION("denormalizeUri", Napi_DenormalizeUri),
160         DECLARE_NAPI_FUNCTION("notifyChange", Napi_NotifyChange),
161         DECLARE_NAPI_FUNCTION("addTemplate", Napi_AddTemplate),
162         DECLARE_NAPI_FUNCTION("delTemplate", Napi_DelTemplate),
163         DECLARE_NAPI_FUNCTION("publish", Napi_Publish),
164         DECLARE_NAPI_FUNCTION("getPublishedData", Napi_GetPublishedData),
165         DECLARE_NAPI_FUNCTION("close", Napi_Close),
166     };
167     NAPI_CALL(env, napi_define_class(env, "DataShareHelper", NAPI_AUTO_LENGTH, Initialize, nullptr,
168         sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons));
169     napi_create_reference(env, cons, 1, &constructor_);
170     return cons;
171 }
172 
Initialize(napi_env env,napi_callback_info info)173 napi_value NapiDataShareHelper::Initialize(napi_env env, napi_callback_info info)
174 {
175     LOG_DEBUG("Start");
176     napi_value self = nullptr;
177     size_t argc = ARGS_MAX_COUNT;
178     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
179     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
180     if (argc <= 1) {
181         LOG_ERROR("Parameters error, need at least 2 parameters!");
182         return nullptr;
183     }
184     auto *proxy = new (std::nothrow) NapiDataShareHelper();
185     if (proxy == nullptr) {
186         return nullptr;
187     }
188     auto finalize = [](napi_env env, void *data, void *hint) {
189         NapiDataShareHelper *proxy = reinterpret_cast<NapiDataShareHelper *>(data);
190         delete proxy;
191     };
192     if (napi_wrap(env, self, proxy, finalize, nullptr, nullptr) != napi_ok) {
193         finalize(env, proxy, nullptr);
194         return nullptr;
195     }
196     return self;
197 }
198 
Napi_Insert(napi_env env,napi_callback_info info)199 napi_value NapiDataShareHelper::Napi_Insert(napi_env env, napi_callback_info info)
200 {
201     auto context = std::make_shared<ContextInfo>();
202     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
203         if (argc != 2 && argc != 3) {
204             context->error = std::make_shared<ParametersNumError>("2 or 3");
205             return napi_invalid_arg;
206         }
207 
208         if (!GetUri(env, argv[0], context->uri)) {
209             context->error = std::make_shared<ParametersTypeError>("uri", "string");
210             return napi_invalid_arg;
211         }
212 
213         context->valueBucket.Clear();
214         if (!GetValueBucketObject(context->valueBucket, env, argv[1])) {
215             context->error = std::make_shared<ParametersTypeError>("valueBucket",
216                 "[string|number|boolean|null|Uint8Array]");
217             return napi_invalid_arg;
218         }
219 
220         return napi_ok;
221     };
222     auto output = [context](napi_env env, napi_value *result) -> napi_status {
223         if (context->resultNumber < 0) {
224             context->error = std::make_shared<InnerError>();
225             return napi_generic_failure;
226         }
227         napi_create_int32(env, context->resultNumber, result);
228         return napi_ok;
229     };
230     auto exec = [context](AsyncCall::Context *ctx) {
231         auto helper = context->proxy->GetHelper();
232         if (helper != nullptr && !context->uri.empty()) {
233             OHOS::Uri uri(context->uri);
234             context->resultNumber = helper->Insert(uri, context->valueBucket);
235             context->status = napi_ok;
236         } else {
237             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
238                 helper == nullptr, context->uri.empty());
239             context->error = std::make_shared<HelperAlreadyClosedError>();
240         }
241     };
242     context->SetAction(std::move(input), std::move(output));
243     AsyncCall asyncCall(env, info, context);
244     return asyncCall.Call(env, exec);
245 }
246 
Napi_Delete(napi_env env,napi_callback_info info)247 napi_value NapiDataShareHelper::Napi_Delete(napi_env env, napi_callback_info info)
248 {
249     auto context = std::make_shared<ContextInfo>();
250     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
251         if (argc != 2 && argc != 3) {
252             context->error = std::make_shared<ParametersNumError>("2 or 3");
253             return napi_invalid_arg;
254         }
255 
256         if (!GetUri(env, argv[0], context->uri)) {
257             context->error = std::make_shared<ParametersTypeError>("uri", "string");
258             return napi_invalid_arg;
259         }
260 
261         if (!DataShareJSUtils::UnwrapDataSharePredicates(env, argv[1], context->predicates)) {
262             context->error = std::make_shared<ParametersTypeError>("predicates", "DataSharePredicates");
263             return napi_invalid_arg;
264         }
265         return napi_ok;
266     };
267     auto output = [context](napi_env env, napi_value *result) -> napi_status {
268         if (context->resultNumber < 0) {
269             context->error = std::make_shared<InnerError>();
270             return napi_generic_failure;
271         }
272         napi_create_int32(env, context->resultNumber, result);
273         return napi_ok;
274     };
275     auto exec = [context](AsyncCall::Context *ctx) {
276         auto helper = context->proxy->GetHelper();
277         if (helper != nullptr && !context->uri.empty()) {
278             OHOS::Uri uri(context->uri);
279             context->resultNumber = helper->Delete(uri, context->predicates);
280             context->status = napi_ok;
281         } else {
282             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
283                 helper == nullptr, context->uri.empty());
284             context->error = std::make_shared<HelperAlreadyClosedError>();
285         }
286     };
287     context->SetAction(std::move(input), std::move(output));
288     AsyncCall asyncCall(env, info, context);
289     return asyncCall.Call(env, exec);
290 }
291 
Napi_Query(napi_env env,napi_callback_info info)292 napi_value NapiDataShareHelper::Napi_Query(napi_env env, napi_callback_info info)
293 {
294     auto context = std::make_shared<ContextInfo>();
295     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
296         if (argc != 3 && argc != 4) {
297             context->error = std::make_shared<ParametersNumError>("3 or 4");
298             return napi_invalid_arg;
299         }
300 
301         if (!GetUri(env, argv[0], context->uri)) {
302             context->error = std::make_shared<ParametersTypeError>("uri", "string");
303             return napi_invalid_arg;
304         }
305 
306         if (!DataShareJSUtils::UnwrapDataSharePredicates(env, argv[1], context->predicates)) {
307             context->error = std::make_shared<ParametersTypeError>("predicates", "DataSharePredicates");
308             return napi_invalid_arg;
309         }
310 
311         context->columns = DataShareJSUtils::Convert2StrVector(env, argv[2], DataShareJSUtils::DEFAULT_BUF_SIZE);
312         return napi_ok;
313     };
314     auto output = [context](napi_env env, napi_value *result) -> napi_status {
315         if (context->businessError.GetCode() != 0) {
316             LOG_DEBUG("query failed, errorCode : %{public}d", context->businessError.GetCode());
317             context->error = std::make_shared<BusinessError>(context->businessError.GetCode(),
318                 context->businessError.GetMessage());
319             return napi_generic_failure;
320         }
321 
322         if (context->resultObject == nullptr) {
323             context->error = std::make_shared<InnerError>();
324             return napi_generic_failure;
325         }
326         *result = DataShareResultSetProxy::NewInstance(env, context->resultObject);
327         context->resultObject = nullptr;
328         return napi_ok;
329     };
330     auto exec = [context](AsyncCall::Context *ctx) {
331         auto helper = context->proxy->GetHelper();
332         if (helper != nullptr && !context->uri.empty()) {
333             OHOS::Uri uri(context->uri);
334             context->resultObject = helper->Query(uri, context->predicates, context->columns,
335                 &(context->businessError));
336             context->status = napi_ok;
337         } else {
338             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
339                 helper == nullptr, context->uri.empty());
340             context->error = std::make_shared<HelperAlreadyClosedError>();
341         }
342     };
343     context->SetAction(std::move(input), std::move(output));
344     AsyncCall asyncCall(env, info, context);
345     return asyncCall.Call(env, exec);
346 }
347 
Napi_Update(napi_env env,napi_callback_info info)348 napi_value NapiDataShareHelper::Napi_Update(napi_env env, napi_callback_info info)
349 {
350     auto context = std::make_shared<ContextInfo>();
351     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
352         if (argc != 3 && argc != 4) {
353             context->error = std::make_shared<ParametersNumError>("3 or 4");
354             return napi_invalid_arg;
355         }
356 
357         if (!GetUri(env, argv[0], context->uri)) {
358             context->error = std::make_shared<ParametersTypeError>("uri", "string");
359             return napi_invalid_arg;
360         }
361 
362         if (!DataShareJSUtils::UnwrapDataSharePredicates(env, argv[1], context->predicates)) {
363             context->error = std::make_shared<ParametersTypeError>("predicates", "DataSharePredicates");
364             return napi_invalid_arg;
365         }
366 
367         context->valueBucket.Clear();
368         if (!GetValueBucketObject(context->valueBucket, env, argv[2])) {
369             context->error = std::make_shared<ParametersTypeError>("valueBucket",
370                 "[string|number|boolean|null|Uint8Array]");
371             return napi_invalid_arg;
372         }
373         return napi_ok;
374     };
375     auto output = [context](napi_env env, napi_value *result) -> napi_status {
376         if (context->resultNumber < 0) {
377             context->error = std::make_shared<InnerError>();
378             return napi_generic_failure;
379         }
380         napi_create_int32(env, context->resultNumber, result);
381         return napi_ok;
382     };
383     auto exec = [context](AsyncCall::Context *ctx) {
384         auto helper = context->proxy->GetHelper();
385         if (helper != nullptr && !context->uri.empty()) {
386             OHOS::Uri uri(context->uri);
387             context->resultNumber = helper->Update(uri, context->predicates, context->valueBucket);
388             context->status = napi_ok;
389         } else {
390             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
391                 helper == nullptr, context->uri.empty());
392             context->error = std::make_shared<HelperAlreadyClosedError>();
393         }
394     };
395     context->SetAction(std::move(input), std::move(output));
396     AsyncCall asyncCall(env, info, context);
397     return asyncCall.Call(env, exec);
398 }
399 
Napi_BatchUpdate(napi_env env,napi_callback_info info)400 napi_value NapiDataShareHelper::Napi_BatchUpdate(napi_env env, napi_callback_info info)
401 {
402     auto context = std::make_shared<ContextInfo>();
403     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
404         if (argc != 1) {
405             context->error = std::make_shared<ParametersNumError>("1");
406             return napi_invalid_arg;
407         }
408         if (DataShareJSUtils::Convert2Value(env, argv[0], context->updateOperations) != napi_ok) {
409             context->error = std::make_shared<ParametersTypeError>("operations",
410                 "Record<string, Array<UpdateOperation>>");
411             return napi_invalid_arg;
412         }
413         return napi_ok;
414     };
415     auto output = [context](napi_env env, napi_value *result) -> napi_status {
416         if (context->resultNumber < 0) {
417             context->error = std::make_shared<InnerError>();
418             return napi_generic_failure;
419         }
420         *result = DataShareJSUtils::Convert2JSValue(env, context->batchUpdateResult);
421         return napi_ok;
422     };
423     auto exec = [context](AsyncCall::Context *ctx) {
424         auto helper = context->proxy->GetHelper();
425         if (helper != nullptr && !context->updateOperations.empty()) {
426             context->resultNumber = helper->BatchUpdate(context->updateOperations, context->batchUpdateResult);
427             context->status = napi_ok;
428         } else {
429             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->updateOperations is empty : %{public}d",
430                 helper == nullptr, context->updateOperations.empty());
431             context->error = std::make_shared<HelperAlreadyClosedError>();
432         }
433     };
434     context->SetAction(std::move(input), std::move(output));
435     AsyncCall asyncCall(env, info, context);
436     return asyncCall.Call(env, exec);
437 }
438 
Napi_BatchInsert(napi_env env,napi_callback_info info)439 napi_value NapiDataShareHelper::Napi_BatchInsert(napi_env env, napi_callback_info info)
440 {
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 
448         if (!GetUri(env, argv[0], context->uri)) {
449             context->error = std::make_shared<ParametersTypeError>("uri", "string");
450             return napi_invalid_arg;
451         }
452         if (DataShareJSUtils::Convert2Value(env, argv[1], context->values) != napi_ok) {
453             context->error = std::make_shared<ParametersTypeError>("valueBucket",
454                 "[string|number|boolean|null|Uint8Array]");
455             return napi_invalid_arg;
456         }
457         return napi_ok;
458     };
459     auto output = [context](napi_env env, napi_value *result) -> napi_status {
460         if (context->resultNumber < 0) {
461             context->error = std::make_shared<InnerError>();
462             return napi_generic_failure;
463         }
464         napi_create_int32(env, context->resultNumber, result);
465         return napi_ok;
466     };
467     auto exec = [context](AsyncCall::Context *ctx) {
468         auto helper = context->proxy->GetHelper();
469         if (helper != nullptr && !context->uri.empty()) {
470             OHOS::Uri uri(context->uri);
471             context->resultNumber = helper->BatchInsert(uri, context->values);
472             context->status = napi_ok;
473         } else {
474             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
475                 helper == nullptr, context->uri.empty());
476             context->error = std::make_shared<HelperAlreadyClosedError>();
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_NormalizeUri(napi_env env,napi_callback_info info)484 napi_value NapiDataShareHelper::Napi_NormalizeUri(napi_env env, napi_callback_info info)
485 {
486     auto context = std::make_shared<ContextInfo>();
487     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
488         if (argc != 1 && argc != 2) {
489             context->error = std::make_shared<ParametersNumError>("1 or 2");
490             return napi_invalid_arg;
491         }
492         if (!GetUri(env, argv[0], context->uri)) {
493             context->error = std::make_shared<ParametersTypeError>("uri", "string");
494             return napi_invalid_arg;
495         }
496         return napi_ok;
497     };
498     auto output = [context](napi_env env, napi_value *result) -> napi_status {
499         napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
500         return napi_ok;
501     };
502     auto exec = [context](AsyncCall::Context *ctx) {
503         auto helper = context->proxy->GetHelper();
504         if (helper != nullptr && !context->uri.empty()) {
505             OHOS::Uri uri(context->uri);
506             Uri uriValue = helper->NormalizeUri(uri);
507             context->resultString = uriValue.ToString();
508             context->status = napi_ok;
509         } else {
510             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
511                 helper == nullptr, context->uri.empty());
512             context->error = std::make_shared<HelperAlreadyClosedError>();
513         }
514     };
515     context->SetAction(std::move(input), std::move(output));
516     AsyncCall asyncCall(env, info, context);
517     return asyncCall.Call(env, exec);
518 }
519 
Napi_DenormalizeUri(napi_env env,napi_callback_info info)520 napi_value NapiDataShareHelper::Napi_DenormalizeUri(napi_env env, napi_callback_info info)
521 {
522     auto context = std::make_shared<ContextInfo>();
523     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
524         if (argc != 1 && argc != 2) {
525             context->error = std::make_shared<ParametersNumError>("1 or 2");
526             return napi_invalid_arg;
527         }
528         if (!GetUri(env, argv[0], context->uri)) {
529             context->error = std::make_shared<ParametersTypeError>("uri", "string");
530             return napi_invalid_arg;
531         }
532         return napi_ok;
533     };
534     auto output = [context](napi_env env, napi_value *result) -> napi_status {
535         napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
536         return napi_ok;
537     };
538     auto exec = [context](AsyncCall::Context *ctx) {
539         auto helper = context->proxy->GetHelper();
540         if (helper != nullptr && !context->uri.empty()) {
541             OHOS::Uri uri(context->uri);
542             Uri uriValue = helper->DenormalizeUri(uri);
543             context->resultString = uriValue.ToString();
544             context->status = napi_ok;
545         } else {
546             LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
547                 helper == nullptr, context->uri.empty());
548             context->error = std::make_shared<HelperAlreadyClosedError>();
549         }
550     };
551     context->SetAction(std::move(input), std::move(output));
552     AsyncCall asyncCall(env, info, context);
553     return asyncCall.Call(env, exec);
554 }
555 
Notify(const std::shared_ptr<NapiDataShareHelper::ContextInfo> context,std::shared_ptr<DataShareHelper> helper)556 void NapiDataShareHelper::Notify(const std::shared_ptr<NapiDataShareHelper::ContextInfo> context,
557     std::shared_ptr<DataShareHelper> helper)
558 {
559     if (!context->isNotifyDetails) {
560         if (!context->uri.empty()) {
561             Uri uri(context->uri);
562             helper->NotifyChange(uri);
563             context->status = napi_ok;
564             return;
565         }
566         LOG_ERROR("context->isNotifyDetails is false, but context->uri is empty");
567         context->error = std::make_shared<ParametersTypeError>("uri", "not empty");
568         return;
569     }
570     helper->NotifyChangeExt(context->changeInfo);
571     context->status = napi_ok;
572     return;
573 }
574 
Napi_NotifyChange(napi_env env,napi_callback_info info)575 napi_value NapiDataShareHelper::Napi_NotifyChange(napi_env env, napi_callback_info info)
576 {
577     auto context = std::make_shared<ContextInfo>();
578     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
579         if (argc != 1 && argc != 2) {
580             context->error = std::make_shared<ParametersNumError>("1 or 2");
581             return napi_invalid_arg;
582         }
583         napi_valuetype valueType;
584         napi_typeof(env, argv[0], &valueType);
585         if (valueType != napi_string) {
586             context->isNotifyDetails = true;
587             if (DataShareJSUtils::Convert2Value(env, argv[0], context->changeInfo) != napi_ok) {
588                 context->error = std::make_shared<ParametersTypeError>("ChangeInfo", "valid");
589                 return napi_invalid_arg;
590             }
591         } else {
592             GetUri(env, argv[0], context->uri);
593         }
594         return napi_ok;
595     };
596     auto output = [context](napi_env env, napi_value *result) -> napi_status {
597         napi_get_null(env, result);
598         return napi_ok;
599     };
600     auto exec = [context](AsyncCall::Context *ctx) {
601         auto helper = context->proxy->GetHelper();
602         if (helper != nullptr) {
603             Notify(context, helper);
604         } else {
605             LOG_ERROR("helper == nullptr : %{public}d", helper == nullptr);
606             context->error = std::make_shared<HelperAlreadyClosedError>();
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_AddTemplate(napi_env env,napi_callback_info info)614 napi_value NapiDataShareHelper::Napi_AddTemplate(napi_env env, napi_callback_info info)
615 {
616     napi_value self = nullptr;
617     size_t argc = MAX_ARGC;
618     napi_value argv[MAX_ARGC] = { nullptr };
619     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
620     std::shared_ptr<Error> error = nullptr;
621     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_THREE, error = std::make_shared<ParametersNumError>("3"), error,
622         nullptr);
623 
624     NapiDataShareHelper *proxy = nullptr;
625     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), nullptr);
626     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
627     auto helper = proxy->GetHelper();
628     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, helper != nullptr, error = std::make_shared<HelperAlreadyClosedError>(), error,
629         nullptr);
630 
631     napi_valuetype valueType;
632     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
633     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string,
634         error = std::make_shared<ParametersTypeError>("uri", "string"), error, nullptr);
635     std::string uri = DataShareJSUtils::Convert2String(env, argv[0]);
636     NAPI_ASSERT_BASE(env, !uri.empty(), "convert uri failed", nullptr);
637 
638     NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
639     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string,
640         error = std::make_shared<ParametersTypeError>("subscriberId", "string"), error, nullptr);
641     std::string subscriberId = DataShareJSUtils::Convert2String(env, argv[1]);
642 
643     NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
644     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object,
645         error = std::make_shared<ParametersTypeError>("template", "Template"), error, nullptr);
646     Template tpl = DataShareJSUtils::Convert2Template(env, argv[PARAM2]);
647 
648     auto res = helper->AddQueryTemplate(uri, atoll(subscriberId.c_str()), tpl);
649     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, res != E_URI_NOT_EXIST && res != E_BUNDLE_NAME_NOT_EXIST,
650         error = std::make_shared<UriNotExistError>(), error, nullptr);
651     return DataShareJSUtils::Convert2JSValue(env, res);
652 }
653 
Napi_DelTemplate(napi_env env,napi_callback_info info)654 napi_value NapiDataShareHelper::Napi_DelTemplate(napi_env env, napi_callback_info info)
655 {
656     napi_value self = nullptr;
657     size_t argc = MAX_ARGC;
658     napi_value argv[MAX_ARGC] = { nullptr };
659     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
660     std::shared_ptr<Error> error = nullptr;
661     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_TWO, error = std::make_shared<ParametersNumError>("2"), error,
662         nullptr);
663 
664     NapiDataShareHelper *proxy = nullptr;
665     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), nullptr);
666     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
667     auto helper = proxy->GetHelper();
668     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, helper != nullptr, error = std::make_shared<HelperAlreadyClosedError>(), error,
669         nullptr);
670 
671     napi_valuetype valueType;
672     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
673     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string,
674         error = std::make_shared<ParametersTypeError>("uri", "string"), error, nullptr);
675     std::string uri = DataShareJSUtils::Convert2String(env, argv[0]);
676     NAPI_ASSERT_BASE(env, !uri.empty(), "convert uri failed", nullptr);
677 
678     NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
679     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string,
680         error = std::make_shared<ParametersTypeError>("subscriberId", "string"), error, nullptr);
681     std::string subscriberId = DataShareJSUtils::Convert2String(env, argv[1]);
682 
683     auto res = helper->DelQueryTemplate(uri, atoll(subscriberId.c_str()));
684     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, res != E_URI_NOT_EXIST && res != E_BUNDLE_NAME_NOT_EXIST,
685         error = std::make_shared<UriNotExistError>(), error, nullptr);
686     return DataShareJSUtils::Convert2JSValue(env, res);
687 }
688 
Napi_Publish(napi_env env,napi_callback_info info)689 napi_value NapiDataShareHelper::Napi_Publish(napi_env env, napi_callback_info info)
690 {
691     auto context = std::make_shared<ContextInfo>();
692     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
693         if (argc != 2 && argc != 3 && argc != 4) {
694             context->error = std::make_shared<ParametersNumError>("2 or 3 or 4");
695             return napi_invalid_arg;
696         }
697         napi_valuetype valueType;
698         NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg);
699         NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object,
700             context->error = std::make_shared<ParametersTypeError>("data", "Data"), napi_invalid_arg);
701         NAPI_CALL_BASE(env, napi_typeof(env, argv[1], &valueType), napi_invalid_arg);
702         NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_string,
703             context->error = std::make_shared<ParametersTypeError>("bundleName", "string"), napi_invalid_arg);
704         context->publishData = DataShareJSUtils::Convert2PublishedData(env, argv[0]);
705         context->bundleName = DataShareJSUtils::Convert2String(env, argv[1]);
706         if (argc > 2) {
707             NAPI_CALL_BASE(env, napi_typeof(env, argv[PARAM2], &valueType), napi_invalid_arg);
708             if (valueType == napi_number) {
709                 napi_get_value_int32(env, argv[PARAM2], &(context->publishData.version_));
710             }
711         }
712         return napi_ok;
713     };
714     auto output = [context](napi_env env, napi_value *result) -> napi_status {
715         NAPI_ASSERT_BASE(env, context->status == napi_ok, "exec failed", napi_generic_failure);
716         for (auto &operationResult : context->results) {
717             if (operationResult.errCode_ == E_BUNDLE_NAME_NOT_EXIST) {
718                 context->error = std::make_shared<DataAreaNotExistError>();
719                 return napi_generic_failure;
720             }
721         }
722         *result = DataShareJSUtils::Convert2JSValue(env, context->results);
723         context->results.clear();
724         return napi_ok;
725     };
726     auto exec = [context](AsyncCall::Context *ctx) {
727         auto helper = context->proxy->GetHelper();
728         if (helper == nullptr) {
729             LOG_ERROR("dataShareHelper_ is nullptr");
730             context->error = std::make_shared<HelperAlreadyClosedError>();
731             return;
732         }
733         context->results = helper->Publish(context->publishData, context->bundleName);
734         context->status = napi_ok;
735     };
736     context->SetAction(std::move(input), std::move(output));
737     AsyncCall asyncCall(env, info, context);
738     return asyncCall.Call(env, exec);
739 }
740 
Napi_GetPublishedData(napi_env env,napi_callback_info info)741 napi_value NapiDataShareHelper::Napi_GetPublishedData(napi_env env, napi_callback_info info)
742 {
743     auto context = std::make_shared<ContextInfo>();
744     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
745         if (argc != 1 && argc != 2) {
746             context->error = std::make_shared<ParametersNumError>("1 or 2");
747             return napi_invalid_arg;
748         }
749         napi_valuetype valueType;
750         NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg);
751         NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_string,
752             context->error = std::make_shared<ParametersTypeError>("bundleName", "string"), napi_invalid_arg);
753         context->bundleName = DataShareJSUtils::Convert2String(env, argv[0]);
754         return napi_ok;
755     };
756     auto output = [context](napi_env env, napi_value *result) -> napi_status {
757         NAPI_ASSERT_BASE(env, context->status == napi_ok, "exec failed", napi_generic_failure);
758         if (context->resultNumber == E_BUNDLE_NAME_NOT_EXIST) {
759             context->error = std::make_shared<DataAreaNotExistError>();
760             return napi_generic_failure;
761         }
762         *result = DataShareJSUtils::Convert2JSValue(env, context->publishData.datas_);
763         return napi_ok;
764     };
765     auto exec = [context](AsyncCall::Context *ctx) {
766         auto helper = context->proxy->GetHelper();
767         if (helper == nullptr) {
768             LOG_ERROR("dataShareHelper_ is nullptr");
769             context->error = std::make_shared<HelperAlreadyClosedError>();
770             return;
771         }
772         context->publishData = helper->GetPublishedData(context->bundleName,
773             context->resultNumber);
774         context->status = napi_ok;
775     };
776     context->SetAction(std::move(input), std::move(output));
777     AsyncCall asyncCall(env, info, context);
778     return asyncCall.Call(env, exec);
779 }
780 
Napi_On(napi_env env,napi_callback_info info)781 napi_value NapiDataShareHelper::Napi_On(napi_env env, napi_callback_info info)
782 {
783     napi_value self = nullptr;
784     size_t argc = MAX_ARGC;
785     napi_value argv[MAX_ARGC] = { nullptr };
786     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
787     std::shared_ptr<Error> error = nullptr;
788     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_THREE || argc == ARGS_FOUR,
789         error = std::make_shared<ParametersNumError>("3 or 4"), error, nullptr);
790     napi_valuetype valueType;
791     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
792     if (valueType != napi_string) {
793         LOG_ERROR("type is not string");
794         return nullptr;
795     }
796     std::string type = DataShareJSUtils::Convert2String(env, argv[0]);
797     if (type == "rdbDataChange") {
798         return Napi_SubscribeRdbObserver(env, argc, argv, self);
799     } else if (type == "publishedDataChange") {
800         return Napi_SubscribePublishedObserver(env, argc, argv, self);
801     } else if (type == "dataChange") {
802         return Napi_RegisterObserver(env, argc, argv, self);
803     }
804     LOG_ERROR("wrong register type : %{public}s", type.c_str());
805     return nullptr;
806 }
Napi_RegisterObserver(napi_env env,size_t argc,napi_value * argv,napi_value self)807 napi_value NapiDataShareHelper::Napi_RegisterObserver(napi_env env, size_t argc, napi_value *argv, napi_value self)
808 {
809     NapiDataShareHelper* proxy = nullptr;
810     std::shared_ptr<Error> error = nullptr;
811     napi_valuetype valueType;
812     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void**>(&proxy)), nullptr);
813     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
814     auto helper = proxy->GetHelper();
815     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, helper != nullptr, error = std::make_shared<HelperAlreadyClosedError>(), error,
816         nullptr);
817     if (argc == ARGS_THREE) {
818         NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType));
819         NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string,
820             error = std::make_shared<ParametersTypeError>("uri", "string"), error, nullptr);
821         std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
822         NAPI_ASSERT_CALL_ERRCODE_SYNC(env, !uri.empty(),
823             error = std::make_shared<ParametersTypeError>("uri", "not empty"), error, nullptr);
824         NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
825         NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_function,
826             error = std::make_shared<ParametersTypeError>("callback", "function"), error, nullptr);
827         proxy->RegisteredObserver(env, uri, argv[PARAM2], std::move(helper));
828         return nullptr;
829     }
830     if (argc == ARGS_FOUR) {
831         NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType));
832         NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_number,
833             error = std::make_shared<ParametersTypeError>("SubscriptionType", "number"), error, nullptr);
834         int32_t value;
835         napi_get_value_int32(env, argv[PARAM1], &value);
836         NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
837         NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string,
838             error = std::make_shared<ParametersTypeError>("uri", "string"), error, nullptr);
839         std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM2]);
840         NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &valueType));
841         NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_function,
842             error = std::make_shared<ParametersTypeError>("callback", "function"), error, nullptr);
843         proxy->RegisteredObserver(env, uri, argv[PARAM3], std::move(helper), true);
844         return nullptr;
845     }
846     return nullptr;
847 }
848 
Napi_Off(napi_env env,napi_callback_info info)849 napi_value NapiDataShareHelper::Napi_Off(napi_env env, napi_callback_info info)
850 {
851     napi_value self = nullptr;
852     size_t argc = MAX_ARGC;
853     napi_value argv[MAX_ARGC] = { nullptr };
854     std::shared_ptr<Error> error = nullptr;
855     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
856     NAPI_ASSERT(env, argc == ARGS_TWO || argc == ARGS_THREE || argc == ARGS_FOUR, "wrong count of args");
857 
858     napi_valuetype valueType;
859     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
860     if (valueType != napi_string) {
861         LOG_ERROR("type is not string");
862         return nullptr;
863     }
864     std::string type = DataShareJSUtils::Convert2String(env, argv[0]);
865     if (type == "rdbDataChange") {
866         return Napi_UnsubscribeRdbObserver(env, argc, argv, self);
867     } else if (type == "publishedDataChange") {
868         return Napi_UnsubscribePublishedObserver(env, argc, argv, self);
869     } else if (type == "dataChange") {
870         return Napi_UnregisterObserver(env, argc, argv, self);
871     }
872     LOG_ERROR("wrong register type : %{public}s", type.c_str());
873     return nullptr;
874 }
875 
Napi_UnregisterObserver(napi_env env,size_t argc,napi_value * argv,napi_value self)876 napi_value NapiDataShareHelper::Napi_UnregisterObserver(napi_env env, size_t argc, napi_value *argv, napi_value self)
877 {
878     std::shared_ptr<Error> error = nullptr;
879     NapiDataShareHelper* proxy = nullptr;
880     napi_valuetype type;
881     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void**>(&proxy)), nullptr);
882     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
883     auto helper = proxy->GetHelper();
884     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, helper != nullptr, error = std::make_shared<HelperAlreadyClosedError>(), error,
885         nullptr);
886     NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &type));
887     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, type == napi_string || type == napi_number,
888         error = std::make_shared<ParametersTypeError>("argv[1]", "string or number"), error, nullptr);
889     if (type == napi_string) {
890         NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_TWO || argc == ARGS_THREE,
891             error = std::make_shared<ParametersNumError>("2 or 3"), error, nullptr);
892         std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
893         if (argc == ARGS_THREE) {
894             NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &type));
895             NAPI_ASSERT_CALL_ERRCODE_SYNC(env, type == napi_function || type == napi_undefined || type == napi_null,
896                 error = std::make_shared<ParametersTypeError>("callback", "function"), error, nullptr);
897             if (type == napi_function) {
898                 proxy->UnRegisteredObserver(env, uri, argv[PARAM2], std::move(helper));
899                 return nullptr;
900             }
901         }
902         proxy->UnRegisteredObserver(env, uri, std::move(helper));
903         return nullptr;
904     }
905     if (type == napi_number) {
906         NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_THREE || argc == ARGS_FOUR,
907             error = std::make_shared<ParametersNumError>("3 or 4"), error, nullptr);
908         NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &type));
909         NAPI_ASSERT_CALL_ERRCODE_SYNC(env, type == napi_string,
910             error = std::make_shared<ParametersTypeError>("uri", "string"), error, nullptr);
911         std::string uriStr = DataShareJSUtils::Convert2String(env, argv[PARAM2]);
912         if (argc == ARGS_FOUR) {
913             NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &type));
914             NAPI_ASSERT_CALL_ERRCODE_SYNC(env, type == napi_function || type == napi_undefined || type == napi_null,
915                 error = std::make_shared<ParametersTypeError>("callback", "function"), error, nullptr);
916             if (type == napi_function) {
917                 proxy->UnRegisteredObserver(env, uriStr, argv[PARAM3], std::move(helper), true);
918                 return nullptr;
919             }
920         }
921         proxy->UnRegisteredObserver(env, uriStr, std::move(helper), true);
922         return nullptr;
923     }
924     return nullptr;
925 }
926 
Napi_Close(napi_env env,napi_callback_info info)927 napi_value NapiDataShareHelper::Napi_Close(napi_env env, napi_callback_info info)
928 {
929     auto context = std::make_shared<ContextInfo>();
930     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
931         return napi_ok;
932     };
933     auto output = [context](napi_env env, napi_value *result) -> napi_status {
934         napi_get_null(env, result);
935         return napi_ok;
936     };
937     auto exec = [context](AsyncCall::Context *ctx) {
938         auto helper = context->proxy->GetHelper();
939         if (helper == nullptr) {
940             context->status = napi_ok;
941             return;
942         }
943         if (!helper->Release()) {
944             context->error = std::make_shared<InnerError>();
945             return;
946         }
947         context->proxy->SetHelper(nullptr);
948         LOG_INFO("Close dataShareHelper succeed.");
949         context->status = napi_ok;
950     };
951     context->SetAction(std::move(input), std::move(output));
952     AsyncCall asyncCall(env, info, context);
953     return asyncCall.Call(env, exec);
954 }
955 
HasRegisteredObserver(napi_env env,std::list<sptr<NAPIDataShareObserver>> & list,napi_value callback)956 bool NapiDataShareHelper::HasRegisteredObserver(napi_env env, std::list<sptr<NAPIDataShareObserver>> &list,
957     napi_value callback)
958 {
959     for (auto &it : list) {
960         if (DataShareJSUtils::Equals(env, callback, it->observer_->GetCallback())) {
961             LOG_DEBUG("The observer has already subscribed.");
962             return true;
963         }
964     }
965     return false;
966 }
967 
RegisteredObserver(napi_env env,const std::string & uri,napi_value callback,std::shared_ptr<DataShareHelper> helper,bool isNotifyDetails)968 void NapiDataShareHelper::RegisteredObserver(napi_env env, const std::string &uri, napi_value callback,
969     std::shared_ptr<DataShareHelper> helper, bool isNotifyDetails)
970 {
971     std::lock_guard<std::mutex> lck(listMutex_);
972     observerMap_.try_emplace(uri);
973 
974     auto &list = observerMap_.find(uri)->second;
975     if (HasRegisteredObserver(env, list, callback)) {
976         LOG_DEBUG("has registered observer");
977         return;
978     }
979     auto innerObserver = std::make_shared<NAPIInnerObserver>(env, callback);
980     sptr<NAPIDataShareObserver> observer(new (std::nothrow) NAPIDataShareObserver(innerObserver));
981     if (observer == nullptr) {
982         LOG_ERROR("observer is nullptr");
983         return;
984     }
985     if (!isNotifyDetails) {
986         helper->RegisterObserver(Uri(uri), observer);
987     } else {
988         helper->RegisterObserverExt(Uri(uri),
989             std::shared_ptr<DataShareObserver>(observer.GetRefPtr(), [holder = observer](const auto*) {}), false);
990     }
991     list.push_back(observer);
992 }
993 
UnRegisteredObserver(napi_env env,const std::string & uri,napi_value callback,std::shared_ptr<DataShareHelper> helper,bool isNotifyDetails)994 void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string &uri, napi_value callback,
995     std::shared_ptr<DataShareHelper> helper, bool isNotifyDetails)
996 {
997     std::lock_guard<std::mutex> lck(listMutex_);
998     auto obs = observerMap_.find(uri);
999     if (obs == observerMap_.end()) {
1000         LOG_DEBUG("this uri hasn't been registered");
1001         return;
1002     }
1003     auto &list = obs->second;
1004     auto it = list.begin();
1005     while (it != list.end()) {
1006         if (!DataShareJSUtils::Equals(env, callback, (*it)->observer_->GetCallback())) {
1007             ++it;
1008             continue;
1009         }
1010         if (!isNotifyDetails) {
1011             helper->UnregisterObserver(Uri(uri), *it);
1012         } else {
1013             helper->UnregisterObserverExt(Uri(uri),
1014                 std::shared_ptr<DataShareObserver>((*it).GetRefPtr(), [holder = *it](const auto*) {}));
1015         }
1016         (*it)->observer_->DeleteReference();
1017         it = list.erase(it);
1018         break;
1019     }
1020     if (list.empty()) {
1021         observerMap_.erase(uri);
1022     }
1023 }
1024 
UnRegisteredObserver(napi_env env,const std::string & uri,std::shared_ptr<DataShareHelper> helper,bool isNotifyDetails)1025 void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string &uri,
1026     std::shared_ptr<DataShareHelper> helper, bool isNotifyDetails)
1027 {
1028     std::lock_guard<std::mutex> lck(listMutex_);
1029     auto obs = observerMap_.find(uri);
1030     if (obs == observerMap_.end()) {
1031         LOG_DEBUG("this uri hasn't been registered");
1032         return;
1033     }
1034     auto &list = obs->second;
1035     auto it = list.begin();
1036     while (it != list.end()) {
1037         if (!isNotifyDetails) {
1038             helper->UnregisterObserver(Uri(uri), *it);
1039         } else {
1040             helper->UnregisterObserverExt(Uri(uri),
1041                 std::shared_ptr<DataShareObserver>((*it).GetRefPtr(), [holder = *it](const auto*) {}));
1042         }
1043         (*it)->observer_->DeleteReference();
1044         it = list.erase(it);
1045     }
1046     observerMap_.erase(uri);
1047 }
1048 
Napi_SubscribeRdbObserver(napi_env env,size_t argc,napi_value * argv,napi_value self)1049 napi_value NapiDataShareHelper::Napi_SubscribeRdbObserver(napi_env env, size_t argc, napi_value *argv, napi_value self)
1050 {
1051     std::vector<OperationResult> results;
1052     napi_value jsResults = DataShareJSUtils::Convert2JSValue(env, results);
1053     std::shared_ptr<Error> error = nullptr;
1054     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_FOUR, error = std::make_shared<ParametersNumError>("4"), error,
1055         jsResults);
1056 
1057     NapiDataShareHelper *proxy = nullptr;
1058     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), jsResults);
1059     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", jsResults);
1060     auto helper = proxy->GetHelper();
1061     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, helper != nullptr, error = std::make_shared<HelperAlreadyClosedError>(), error,
1062         jsResults);
1063 
1064     napi_valuetype valueType;
1065     NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
1066     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object,
1067         error = std::make_shared<ParametersTypeError>("uris", "Array<String>"), error, jsResults);
1068     std::vector<std::string> uris =
1069         DataShareJSUtils::Convert2StrVector(env, argv[1], DataShareJSUtils::DEFAULT_BUF_SIZE);
1070 
1071     NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
1072     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object,
1073         error = std::make_shared<ParametersTypeError>("templateId", "TemplateId"), error, jsResults);
1074     TemplateId templateId = DataShareJSUtils::Convert2TemplateId(env, argv[PARAM2]);
1075 
1076     NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &valueType));
1077     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_function,
1078         error = std::make_shared<ParametersTypeError>("callback", "function"), error, jsResults);
1079 
1080     if (proxy->jsRdbObsManager_ == nullptr) {
1081         LOG_ERROR("proxy->jsManager_ is nullptr");
1082         return jsResults;
1083     }
1084     results = proxy->jsRdbObsManager_->AddObservers(env, argv[PARAM3], uris, templateId);
1085     return DataShareJSUtils::Convert2JSValue(env, results);
1086 }
1087 
Napi_UnsubscribeRdbObserver(napi_env env,size_t argc,napi_value * argv,napi_value self)1088 napi_value NapiDataShareHelper::Napi_UnsubscribeRdbObserver(napi_env env, size_t argc, napi_value *argv,
1089     napi_value self)
1090 {
1091     std::vector<OperationResult> results;
1092     napi_value jsResults = DataShareJSUtils::Convert2JSValue(env, results);
1093     std::shared_ptr<Error> error = nullptr;
1094     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_THREE || argc == ARGS_FOUR,
1095         error = std::make_shared<ParametersNumError>("3 or 4"), error, jsResults);
1096 
1097     NapiDataShareHelper *proxy = nullptr;
1098     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), jsResults);
1099     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", jsResults);
1100     auto helper = proxy->GetHelper();
1101     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, helper != nullptr, error = std::make_shared<HelperAlreadyClosedError>(), error,
1102         jsResults);
1103 
1104     napi_valuetype valueType;
1105     NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
1106     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object,
1107         error = std::make_shared<ParametersTypeError>("uris", "Array<String>"), error, jsResults);
1108     std::vector<std::string> uris =
1109         DataShareJSUtils::Convert2StrVector(env, argv[1], DataShareJSUtils::DEFAULT_BUF_SIZE);
1110 
1111     NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
1112     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object,
1113         error = std::make_shared<ParametersTypeError>("templateId", "TemplateId"), error, jsResults);
1114     TemplateId templateId = DataShareJSUtils::Convert2TemplateId(env, argv[2]);
1115 
1116     if (proxy->jsRdbObsManager_ == nullptr) {
1117         LOG_ERROR("proxy->jsManager_ is nullptr");
1118         return jsResults;
1119     }
1120 
1121     if (argc == ARGS_FOUR) {
1122         NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &valueType));
1123         NAPI_ASSERT_CALL_ERRCODE_SYNC(env,
1124             valueType == napi_function || valueType == napi_undefined || valueType == napi_null,
1125             error = std::make_shared<ParametersTypeError>("callback", "function"), error, jsResults);
1126         if (valueType == napi_function) {
1127             results = proxy->jsRdbObsManager_->DelObservers(env, argv[PARAM3], uris, templateId);
1128             return DataShareJSUtils::Convert2JSValue(env, results);
1129         }
1130     }
1131     results = proxy->jsRdbObsManager_->DelObservers(env, nullptr, uris, templateId);
1132     return DataShareJSUtils::Convert2JSValue(env, results);
1133 }
1134 
Napi_SubscribePublishedObserver(napi_env env,size_t argc,napi_value * argv,napi_value self)1135 napi_value NapiDataShareHelper::Napi_SubscribePublishedObserver(napi_env env, size_t argc, napi_value *argv,
1136     napi_value self)
1137 {
1138     std::vector<OperationResult> results;
1139     napi_value jsResults = DataShareJSUtils::Convert2JSValue(env, results);
1140     std::shared_ptr<Error> error = nullptr;
1141     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_FOUR, error = std::make_shared<ParametersNumError>("4"), error,
1142         jsResults);
1143 
1144     NapiDataShareHelper *proxy = nullptr;
1145     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), jsResults);
1146     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", jsResults);
1147     auto helper = proxy->GetHelper();
1148     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, helper != nullptr, error = std::make_shared<HelperAlreadyClosedError>(), error,
1149         jsResults);
1150 
1151     napi_valuetype valueType;
1152     NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
1153     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object,
1154         error = std::make_shared<ParametersTypeError>("uris", "Array<String>"), error, jsResults);
1155     std::vector<std::string> uris =
1156         DataShareJSUtils::Convert2StrVector(env, argv[1], DataShareJSUtils::DEFAULT_BUF_SIZE);
1157 
1158     NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
1159     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string,
1160         error = std::make_shared<ParametersTypeError>("subscriberId", "string"), error, jsResults);
1161     std::string subscriberId = DataShareJSUtils::Convert2String(env, argv[PARAM2]);
1162 
1163     NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &valueType));
1164     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_function,
1165         error = std::make_shared<ParametersTypeError>("callback", "function"), error, jsResults);
1166 
1167     if (proxy->jsPublishedObsManager_ == nullptr) {
1168         LOG_ERROR("proxy->jsPublishedObsManager_ is nullptr");
1169         return jsResults;
1170     }
1171     results = proxy->jsPublishedObsManager_->AddObservers(env, argv[PARAM3], uris, atoll(subscriberId.c_str()));
1172     return DataShareJSUtils::Convert2JSValue(env, results);
1173 }
1174 
Napi_UnsubscribePublishedObserver(napi_env env,size_t argc,napi_value * argv,napi_value self)1175 napi_value NapiDataShareHelper::Napi_UnsubscribePublishedObserver(napi_env env, size_t argc, napi_value *argv,
1176     napi_value self)
1177 {
1178     std::vector<OperationResult> results;
1179     napi_value jsResults = DataShareJSUtils::Convert2JSValue(env, results);
1180     std::shared_ptr<Error> error = nullptr;
1181     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_THREE || argc == ARGS_FOUR,
1182         error = std::make_shared<ParametersNumError>("3 or 4"), error, jsResults);
1183 
1184     NapiDataShareHelper *proxy = nullptr;
1185     NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), jsResults);
1186     NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", jsResults);
1187     auto helper = proxy->GetHelper();
1188     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, helper != nullptr, error = std::make_shared<HelperAlreadyClosedError>(), error,
1189         jsResults);
1190 
1191     napi_valuetype valueType;
1192     NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
1193     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object,
1194         error = std::make_shared<ParametersTypeError>("uris", "Array<String>"), error, jsResults);
1195     std::vector<std::string> uris =
1196         DataShareJSUtils::Convert2StrVector(env, argv[1], DataShareJSUtils::DEFAULT_BUF_SIZE);
1197 
1198     NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
1199     NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string,
1200         error = std::make_shared<ParametersTypeError>("subscriberId", "string"), error, jsResults);
1201     std::string subscriberId = DataShareJSUtils::Convert2String(env, argv[PARAM2]);
1202     if (proxy->jsPublishedObsManager_ == nullptr) {
1203         LOG_ERROR("proxy->jsPublishedObsManager_ is nullptr");
1204         return jsResults;
1205     }
1206 
1207     if (argc == ARGS_FOUR) {
1208         NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &valueType));
1209         NAPI_ASSERT_CALL_ERRCODE_SYNC(env,
1210             valueType == napi_function || valueType == napi_undefined || valueType == napi_null,
1211             error = std::make_shared<ParametersTypeError>("callback", "function"), error, jsResults);
1212         if (valueType == napi_function) {
1213             results = proxy->jsPublishedObsManager_->DelObservers(env, argv[PARAM3], uris, atoll(subscriberId.c_str()));
1214             return DataShareJSUtils::Convert2JSValue(env, results);
1215         }
1216     }
1217     results = proxy->jsPublishedObsManager_->DelObservers(env, nullptr, uris, atoll(subscriberId.c_str()));
1218     return DataShareJSUtils::Convert2JSValue(env, results);
1219 }
1220 
EnableSilentProxy(napi_env env,napi_callback_info info)1221 napi_value NapiDataShareHelper::EnableSilentProxy(napi_env env, napi_callback_info info)
1222 {
1223     return SetSilentSwitch(env, info, true);
1224 }
1225 
DisableSilentProxy(napi_env env,napi_callback_info info)1226 napi_value NapiDataShareHelper::DisableSilentProxy(napi_env env, napi_callback_info info)
1227 {
1228     return SetSilentSwitch(env, info, false);
1229 }
1230 
SetSilentSwitch(napi_env env,napi_callback_info info,bool enable)1231 napi_value NapiDataShareHelper::SetSilentSwitch(napi_env env, napi_callback_info info, bool enable)
1232 {
1233     auto context = std::make_shared<CreateContextInfo>();
1234     context->silentSwitch = enable;
1235     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
1236         if (argc != 1 && argc != 2) {
1237             context->error = std::make_shared<ParametersNumError>("1 or 2");
1238             return napi_invalid_arg;
1239         }
1240         context->contextS = OHOS::AbilityRuntime::GetStageModeContext(env, argv[0]);
1241         NAPI_ASSERT_CALL_ERRCODE(env, context->contextS != nullptr,
1242             context->error = std::make_shared<ParametersTypeError>("contextS", "not nullptr"), napi_invalid_arg);
1243         if (argc > 1) {
1244             NAPI_ASSERT_CALL_ERRCODE(env, GetSilentUri(env, argv[1], context->strUri),
1245                 context->error = std::make_shared<ParametersTypeError>("uri", "string"), napi_invalid_arg);
1246         }
1247         return napi_ok;
1248     };
1249     auto output = [context](napi_env env, napi_value *result) -> napi_status {
1250         return napi_ok;
1251     };
1252     auto exec = [context](AsyncCall::Context *ctx) {
1253         OHOS::Uri uri(context->strUri);
1254         DataShareHelper::SetSilentSwitch(uri, context->silentSwitch);
1255     };
1256     context->SetAction(std::move(input), std::move(output));
1257     AsyncCall asyncCall(env, info, context);
1258     return asyncCall.Call(env, exec);
1259 }
1260 
SetHelper(std::shared_ptr<DataShareHelper> dataShareHelper)1261 void NapiDataShareHelper::NapiDataShareHelper::SetHelper(std::shared_ptr<DataShareHelper> dataShareHelper)
1262 {
1263     std::unique_lock<std::shared_mutex> lock(mutex_);
1264     datashareHelper_ = std::move(dataShareHelper);
1265 }
GetHelper()1266 std::shared_ptr<DataShareHelper> NapiDataShareHelper::GetHelper()
1267 {
1268     std::shared_lock<std::shared_mutex> lock(mutex_);
1269     return datashareHelper_;
1270 }
1271 } // namespace DataShare
1272 } // namespace OHOS
1273