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