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