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