1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "napi_datashare_helper.h"
17
18 #include "napi_common_util.h"
19 #include "datashare_helper.h"
20 #include "datashare_log.h"
21 #include "napi_base_context.h"
22 #include "napi_datashare_values_bucket.h"
23 #include "datashare_predicates_proxy.h"
24 #include "datashare_result_set_proxy.h"
25
26 using namespace OHOS::AAFwk;
27 using namespace OHOS::AppExecFwk;
28
29 namespace OHOS {
30 namespace DataShare {
31 constexpr int MAX_ARGC = 6;
32
UnwrapDataSharePredicates(napi_env env,napi_value value)33 static DataSharePredicates UnwrapDataSharePredicates(napi_env env, napi_value value)
34 {
35 auto predicates = DataSharePredicatesProxy::GetNativePredicates(env, value);
36 if (predicates == nullptr) {
37 LOG_ERROR("GetNativePredicates is nullptr.");
38 return {};
39 }
40 return DataSharePredicates(predicates->GetOperationList());
41 }
42
UnwrapValuesBucketArrayFromJS(napi_env env,napi_value param,std::vector<DataShareValuesBucket> & value)43 static bool UnwrapValuesBucketArrayFromJS(napi_env env, napi_value param,
44 std::vector<DataShareValuesBucket> &value)
45 {
46 LOG_DEBUG("Start");
47 uint32_t arraySize = 0;
48 napi_value jsValue = nullptr;
49 std::string strValue = "";
50
51 if (!IsArrayForNapiValue(env, param, arraySize)) {
52 LOG_ERROR("IsArrayForNapiValue is false");
53 return false;
54 }
55
56 value.clear();
57 for (uint32_t i = 0; i < arraySize; i++) {
58 jsValue = nullptr;
59 if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
60 LOG_ERROR("napi_get_element is false");
61 return false;
62 }
63
64 DataShareValuesBucket valueBucket;
65 valueBucket.Clear();
66 if (!GetValueBucketObject(valueBucket, env, jsValue)) {
67 return false;
68 }
69
70 value.push_back(valueBucket);
71 }
72 return true;
73 }
74
GetValuesBucketArray(napi_env env,napi_value param,bool & status)75 static std::vector<DataShareValuesBucket> GetValuesBucketArray(napi_env env, napi_value param, bool &status)
76 {
77 LOG_DEBUG("Start");
78 std::vector<DataShareValuesBucket> result;
79 status = UnwrapValuesBucketArrayFromJS(env, param, result);
80 return result;
81 }
82
GetUri(napi_env env,napi_value jsValue,std::string & uri)83 static bool GetUri(napi_env env, napi_value jsValue, std::string &uri)
84 {
85 LOG_DEBUG("Start");
86 napi_valuetype valuetype = napi_undefined;
87 napi_typeof(env, jsValue, &valuetype);
88 if (valuetype != napi_string) {
89 return false;
90 }
91 uri = DataShareJSUtils::Convert2String(env, jsValue);
92 return true;
93 }
94
Napi_CreateDataShareHelper(napi_env env,napi_callback_info info)95 napi_value NapiDataShareHelper::Napi_CreateDataShareHelper(napi_env env, napi_callback_info info)
96 {
97 LOG_DEBUG("Start");
98 auto ctxInfo = std::make_shared<CreateContextInfo>();
99 auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
100 if (argc != 2 && argc != 3) {
101 ctxInfo->error = std::make_shared<ParametersNumError>("2 or 3");
102 return napi_invalid_arg;
103 }
104 bool isStageMode = false;
105 napi_status status = AbilityRuntime::IsStageContext(env, argv[PARAM0], isStageMode);
106 if (status != napi_ok || !isStageMode) {
107 ctxInfo->isStageMode = false;
108 auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
109 if (!GetUri(env, argv[PARAM0], ctxInfo->strUri)) {
110 ctxInfo->error = std::make_shared<ParametersTypeError>("uri", "string");
111 return napi_invalid_arg;
112 }
113
114 if (ability == nullptr) {
115 ctxInfo->error = std::make_shared<ParametersTypeError>("ability", "not nullptr");
116 return napi_invalid_arg;
117 }
118 ctxInfo->contextF = ability->GetContext();
119 } else {
120 ctxInfo->contextS = OHOS::AbilityRuntime::GetStageModeContext(env, argv[PARAM0]);
121 if (!GetUri(env, argv[PARAM1], ctxInfo->strUri)) {
122 ctxInfo->error = std::make_shared<ParametersTypeError>("uri", "string");
123 return napi_invalid_arg;
124 }
125
126 if (ctxInfo->contextS == nullptr) {
127 ctxInfo->error = std::make_shared<ParametersTypeError>("contextS", "not nullptr");
128 return napi_invalid_arg;
129 }
130 }
131
132 napi_value helperProxy = nullptr;
133 status = napi_new_instance(env, GetConstructor(env), argc, argv, &helperProxy);
134 if ((helperProxy == nullptr) || (status != napi_ok)) {
135 ctxInfo->error = std::make_shared<DataShareHelperInitError>();
136 return napi_generic_failure;
137 }
138 napi_create_reference(env, helperProxy, 1, &(ctxInfo->ref));
139 ctxInfo->env = env;
140 return napi_ok;
141 };
142 auto output = [ctxInfo](napi_env env, napi_value *result) -> napi_status {
143 if (ctxInfo->dataShareHelper == nullptr) {
144 ctxInfo->error = std::make_shared<DataShareHelperInitError>();
145 return napi_generic_failure;
146 }
147 napi_status status = napi_get_reference_value(env, ctxInfo->ref, result);
148 NapiDataShareHelper *proxy = nullptr;
149 status = napi_unwrap(env, *result, reinterpret_cast<void **>(&proxy));
150 if (proxy == nullptr) {
151 LOG_ERROR("proxy is nullptr");
152 return status;
153 }
154 proxy->datashareHelper_ = std::move(ctxInfo->dataShareHelper);
155 return status;
156 };
157 auto exec = [ctxInfo](AsyncCall::Context *ctx) {
158 if (ctxInfo->isStageMode && ctxInfo->contextS != nullptr) {
159 ctxInfo->dataShareHelper = DataShareHelper::Creator(ctxInfo->contextS, ctxInfo->strUri);
160 } else if (!ctxInfo->isStageMode && ctxInfo->contextF != nullptr) {
161 ctxInfo->dataShareHelper = DataShareHelper::Creator(ctxInfo->contextF, ctxInfo->strUri);
162 }
163 };
164 ctxInfo->SetAction(std::move(input), std::move(output));
165 AsyncCall asyncCall(env, info, ctxInfo);
166 return asyncCall.Call(env, exec);
167 }
168
GetConstructor(napi_env env)169 napi_value NapiDataShareHelper::GetConstructor(napi_env env)
170 {
171 napi_value cons = nullptr;
172 napi_property_descriptor clzDes[] = {
173 DECLARE_NAPI_FUNCTION("on", Napi_On),
174 DECLARE_NAPI_FUNCTION("off", Napi_Off),
175 DECLARE_NAPI_FUNCTION("insert", Napi_Insert),
176 DECLARE_NAPI_FUNCTION("delete", Napi_Delete),
177 DECLARE_NAPI_FUNCTION("query", Napi_Query),
178 DECLARE_NAPI_FUNCTION("update", Napi_Update),
179 DECLARE_NAPI_FUNCTION("batchInsert", Napi_BatchInsert),
180 DECLARE_NAPI_FUNCTION("normalizeUri", Napi_NormalizeUri),
181 DECLARE_NAPI_FUNCTION("denormalizeUri", Napi_DenormalizeUri),
182 DECLARE_NAPI_FUNCTION("notifyChange", Napi_NotifyChange),
183 };
184 NAPI_CALL(env, napi_define_class(env, "DataShareHelper", NAPI_AUTO_LENGTH, Initialize, nullptr,
185 sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons));
186 return cons;
187 }
188
Initialize(napi_env env,napi_callback_info info)189 napi_value NapiDataShareHelper::Initialize(napi_env env, napi_callback_info info)
190 {
191 LOG_DEBUG("Start");
192 napi_value self = nullptr;
193 size_t argc = ARGS_MAX_COUNT;
194 napi_value argv[ARGS_MAX_COUNT] = {nullptr};
195 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
196 if (argc <= 1) {
197 LOG_ERROR("Parameters error, need at least 2 parameters!");
198 return nullptr;
199 }
200 auto *proxy = new (std::nothrow) NapiDataShareHelper();
201 if (proxy == nullptr) {
202 return nullptr;
203 }
204 auto finalize = [](napi_env env, void * data, void * hint) {
205 NapiDataShareHelper *proxy = reinterpret_cast<NapiDataShareHelper *>(data);
206 delete proxy;
207 LOG_INFO("NapiDataShareHelper has been deleted successfully!");
208 };
209 if (napi_wrap(env, self, proxy, finalize, nullptr, nullptr) != napi_ok) {
210 finalize(env, proxy, nullptr);
211 return nullptr;
212 }
213 return self;
214 }
215
Napi_OpenFile(napi_env env,napi_callback_info info)216 napi_value NapiDataShareHelper::Napi_OpenFile(napi_env env, napi_callback_info info)
217 {
218 LOG_DEBUG("Start");
219 auto context = std::make_shared<ContextInfo>();
220 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
221 NAPI_ASSERT_BASE(env, argc == 2 || argc == 3, " should 2 or 3 parameters!", napi_invalid_arg);
222 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
223
224 GetUri(env, argv[PARAM0], context->uri);
225
226 napi_valuetype valuetype = napi_undefined;
227 napi_typeof(env, argv[PARAM1], &valuetype);
228 if (valuetype == napi_string) {
229 context->mode = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
230 } else {
231 LOG_ERROR("wrong type, should be napi_string");
232 }
233 return napi_ok;
234 };
235 auto output = [context](napi_env env, napi_value *result) -> napi_status {
236 napi_create_int32(env, context->resultNumber, result);
237 return napi_ok;
238 };
239 auto exec = [context](AsyncCall::Context *ctx) {
240 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
241 OHOS::Uri uri(context->uri);
242 context->resultNumber = context->proxy->datashareHelper_->OpenFile(uri, context->mode);
243 context->status = napi_ok;
244 } else {
245 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
246 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
247 }
248 };
249 context->SetAction(std::move(input), std::move(output));
250 AsyncCall asyncCall(env, info, context);
251 return asyncCall.Call(env, exec);
252 }
253
Napi_Insert(napi_env env,napi_callback_info info)254 napi_value NapiDataShareHelper::Napi_Insert(napi_env env, napi_callback_info info)
255 {
256 LOG_DEBUG("Start");
257 auto context = std::make_shared<ContextInfo>();
258 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
259 if (argc != 2 && argc != 3) {
260 context->error = std::make_shared<ParametersNumError>("2 or 3");
261 return napi_invalid_arg;
262 }
263 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
264
265 if (!GetUri(env, argv[PARAM0], context->uri)) {
266 context->error = std::make_shared<ParametersTypeError>("uri", "string");
267 return napi_invalid_arg;
268 }
269
270 context->valueBucket.Clear();
271 if (!GetValueBucketObject(context->valueBucket, env, argv[PARAM1])) {
272 context->error = std::make_shared<ParametersTypeError>("valueBucket",
273 "[string|number|boolean|null|Uint8Array]");
274 return napi_invalid_arg;
275 }
276
277 return napi_ok;
278 };
279 auto output = [context](napi_env env, napi_value *result) -> napi_status {
280 if (context->resultNumber < 0) {
281 context->error = std::make_shared<InnerError>();
282 return napi_generic_failure;
283 }
284 napi_create_int32(env, context->resultNumber, result);
285 return napi_ok;
286 };
287 auto exec = [context](AsyncCall::Context *ctx) {
288 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
289 OHOS::Uri uri(context->uri);
290 context->resultNumber = context->proxy->datashareHelper_->Insert(uri, context->valueBucket);
291 context->status = napi_ok;
292 } else {
293 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
294 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
295 }
296 };
297 context->SetAction(std::move(input), std::move(output));
298 AsyncCall asyncCall(env, info, context);
299 return asyncCall.Call(env, exec);
300 }
301
Napi_Delete(napi_env env,napi_callback_info info)302 napi_value NapiDataShareHelper::Napi_Delete(napi_env env, napi_callback_info info)
303 {
304 LOG_DEBUG("Start");
305 auto context = std::make_shared<ContextInfo>();
306 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
307 if (argc != 2 && argc != 3) {
308 context->error = std::make_shared<ParametersNumError>("2 or 3");
309 return napi_invalid_arg;
310 }
311 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
312
313 if (!GetUri(env, argv[PARAM0], context->uri)) {
314 context->error = std::make_shared<ParametersTypeError>("uri", "string");
315 return napi_invalid_arg;
316 }
317
318 context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
319 return napi_ok;
320 };
321 auto output = [context](napi_env env, napi_value *result) -> napi_status {
322 if (context->resultNumber < 0) {
323 context->error = std::make_shared<InnerError>();
324 return napi_generic_failure;
325 }
326 napi_create_int32(env, context->resultNumber, result);
327 return napi_ok;
328 };
329 auto exec = [context](AsyncCall::Context *ctx) {
330 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
331 OHOS::Uri uri(context->uri);
332 context->resultNumber = context->proxy->datashareHelper_->Delete(uri, context->predicates);
333 context->status = napi_ok;
334 } else {
335 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
336 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
337 }
338 };
339 context->SetAction(std::move(input), std::move(output));
340 AsyncCall asyncCall(env, info, context);
341 return asyncCall.Call(env, exec);
342 }
343
Napi_Query(napi_env env,napi_callback_info info)344 napi_value NapiDataShareHelper::Napi_Query(napi_env env, napi_callback_info info)
345 {
346 LOG_DEBUG("Start");
347 auto context = std::make_shared<ContextInfo>();
348 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
349 if (argc != 3 && argc != 4) {
350 context->error = std::make_shared<ParametersNumError>("3 or 4");
351 return napi_invalid_arg;
352 }
353 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
354
355 if (!GetUri(env, argv[PARAM0], context->uri)) {
356 context->error = std::make_shared<ParametersTypeError>("uri", "string");
357 return napi_invalid_arg;
358 }
359
360 context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
361
362 context->columns = DataShareJSUtils::Convert2StrVector(env, argv[PARAM2], DataShareJSUtils::DEFAULT_BUF_SIZE);
363 return napi_ok;
364 };
365 auto output = [context](napi_env env, napi_value *result) -> napi_status {
366 if (context->resultObject == nullptr) {
367 context->error = std::make_shared<InnerError>();
368 return napi_generic_failure;
369 }
370 *result = DataShareResultSetProxy::NewInstance(env, context->resultObject);
371 return napi_ok;
372 };
373 auto exec = [context](AsyncCall::Context *ctx) {
374 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
375 OHOS::Uri uri(context->uri);
376 context->resultObject = context->proxy->datashareHelper_->Query(uri, context->predicates, context->columns);
377 context->status = napi_ok;
378 } else {
379 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
380 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
381 }
382 };
383 context->SetAction(std::move(input), std::move(output));
384 AsyncCall asyncCall(env, info, context);
385 return asyncCall.Call(env, exec);
386 }
387
Napi_Update(napi_env env,napi_callback_info info)388 napi_value NapiDataShareHelper::Napi_Update(napi_env env, napi_callback_info info)
389 {
390 LOG_DEBUG("Start");
391 auto context = std::make_shared<ContextInfo>();
392 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
393 if (argc != 3 && argc != 4) {
394 context->error = std::make_shared<ParametersNumError>("3 or 4");
395 return napi_invalid_arg;
396 }
397 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
398
399 if (!GetUri(env, argv[PARAM0], context->uri)) {
400 context->error = std::make_shared<ParametersTypeError>("uri", "string");
401 return napi_invalid_arg;
402 }
403
404 context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
405
406 context->valueBucket.Clear();
407 if (!GetValueBucketObject(context->valueBucket, env, argv[PARAM2])) {
408 context->error = std::make_shared<ParametersTypeError>("valueBucket",
409 "[string|number|boolean|null|Uint8Array]");
410 return napi_invalid_arg;
411 }
412 return napi_ok;
413 };
414 auto output = [context](napi_env env, napi_value *result) -> napi_status {
415 if (context->resultNumber < 0) {
416 context->error = std::make_shared<InnerError>();
417 return napi_generic_failure;
418 }
419 napi_create_int32(env, context->resultNumber, result);
420 return napi_ok;
421 };
422 auto exec = [context](AsyncCall::Context *ctx) {
423 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
424 OHOS::Uri uri(context->uri);
425 context->resultNumber =
426 context->proxy->datashareHelper_->Update(uri, context->predicates, context->valueBucket);
427 context->status = napi_ok;
428 } else {
429 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
430 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
431 }
432 };
433 context->SetAction(std::move(input), std::move(output));
434 AsyncCall asyncCall(env, info, context);
435 return asyncCall.Call(env, exec);
436 }
437
Napi_BatchInsert(napi_env env,napi_callback_info info)438 napi_value NapiDataShareHelper::Napi_BatchInsert(napi_env env, napi_callback_info info)
439 {
440 LOG_DEBUG("Start");
441 auto context = std::make_shared<ContextInfo>();
442 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
443 if (argc != 2 && argc != 3) {
444 context->error = std::make_shared<ParametersNumError>("2 or 3");
445 return napi_invalid_arg;
446 }
447 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
448
449 if (!GetUri(env, argv[PARAM0], context->uri)) {
450 context->error = std::make_shared<ParametersTypeError>("uri", "string");
451 return napi_invalid_arg;
452 }
453 bool status = false;
454 context->values = GetValuesBucketArray(env, argv[PARAM1], status);
455 if (!status) {
456 context->error = std::make_shared<ParametersTypeError>("valueBucket",
457 "[string|number|boolean|null|Uint8Array]");
458 return napi_invalid_arg;
459 }
460 return napi_ok;
461 };
462 auto output = [context](napi_env env, napi_value *result) -> napi_status {
463 if (context->resultNumber < 0) {
464 context->error = std::make_shared<InnerError>();
465 return napi_generic_failure;
466 }
467 napi_create_int32(env, context->resultNumber, result);
468 return napi_ok;
469 };
470 auto exec = [context](AsyncCall::Context *ctx) {
471 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
472 OHOS::Uri uri(context->uri);
473 context->resultNumber = context->proxy->datashareHelper_->BatchInsert(uri, context->values);
474 context->status = napi_ok;
475 } else {
476 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
477 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
478 }
479 };
480 context->SetAction(std::move(input), std::move(output));
481 AsyncCall asyncCall(env, info, context);
482 return asyncCall.Call(env, exec);
483 }
484
Napi_GetType(napi_env env,napi_callback_info info)485 napi_value NapiDataShareHelper::Napi_GetType(napi_env env, napi_callback_info info)
486 {
487 LOG_DEBUG("Start");
488 auto context = std::make_shared<ContextInfo>();
489 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
490 NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
491 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
492
493 GetUri(env, argv[PARAM0], context->uri);
494 return napi_ok;
495 };
496 auto output = [context](napi_env env, napi_value *result) -> napi_status {
497 napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
498 return napi_ok;
499 };
500 auto exec = [context](AsyncCall::Context *ctx) {
501 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
502 OHOS::Uri uri(context->uri);
503 context->resultString = context->proxy->datashareHelper_->GetType(uri);
504 context->status = napi_ok;
505 } else {
506 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
507 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
508 }
509 };
510 context->SetAction(std::move(input), std::move(output));
511 AsyncCall asyncCall(env, info, context);
512 return asyncCall.Call(env, exec);
513 }
514
Napi_GetFileTypes(napi_env env,napi_callback_info info)515 napi_value NapiDataShareHelper::Napi_GetFileTypes(napi_env env, napi_callback_info info)
516 {
517 LOG_DEBUG("Start");
518 auto context = std::make_shared<ContextInfo>();
519 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
520 NAPI_ASSERT_BASE(env, argc == 2 || argc == 3, " should 2 or 3 parameters!", napi_invalid_arg);
521 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
522
523 GetUri(env, argv[PARAM0], context->uri);
524
525 napi_valuetype valuetype = napi_undefined;
526 napi_typeof(env, argv[PARAM1], &valuetype);
527 if (valuetype == napi_string) {
528 context->mimeTypeFilter = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
529 } else {
530 LOG_ERROR("wrong type, should be napi_string");
531 }
532 return napi_ok;
533 };
534 auto output = [context](napi_env env, napi_value *result) -> napi_status {
535 *result = DataShareJSUtils::Convert2JSValue(env, context->resultStrArr);
536 return napi_ok;
537 };
538 auto exec = [context](AsyncCall::Context *ctx) {
539 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
540 OHOS::Uri uri(context->uri);
541 context->resultStrArr = context->proxy->datashareHelper_->GetFileTypes(uri, context->mimeTypeFilter);
542 context->status = napi_ok;
543 } else {
544 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
545 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
546 }
547 };
548 context->SetAction(std::move(input), std::move(output));
549 AsyncCall asyncCall(env, info, context);
550 return asyncCall.Call(env, exec);
551 }
552
Napi_NormalizeUri(napi_env env,napi_callback_info info)553 napi_value NapiDataShareHelper::Napi_NormalizeUri(napi_env env, napi_callback_info info)
554 {
555 LOG_DEBUG("Start");
556 auto context = std::make_shared<ContextInfo>();
557 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
558 NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
559 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
560
561 GetUri(env, argv[PARAM0], context->uri);
562 return napi_ok;
563 };
564 auto output = [context](napi_env env, napi_value *result) -> napi_status {
565 napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
566 return napi_ok;
567 };
568 auto exec = [context](AsyncCall::Context *ctx) {
569 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
570 OHOS::Uri uri(context->uri);
571 Uri uriValue = context->proxy->datashareHelper_->NormalizeUri(uri);
572 context->resultString = uriValue.ToString();
573 context->status = napi_ok;
574 } else {
575 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
576 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
577 }
578 };
579 context->SetAction(std::move(input), std::move(output));
580 AsyncCall asyncCall(env, info, context);
581 return asyncCall.Call(env, exec);
582 }
583
Napi_DenormalizeUri(napi_env env,napi_callback_info info)584 napi_value NapiDataShareHelper::Napi_DenormalizeUri(napi_env env, napi_callback_info info)
585 {
586 LOG_DEBUG("Start");
587 auto context = std::make_shared<ContextInfo>();
588 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
589 NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
590 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
591
592 GetUri(env, argv[PARAM0], context->uri);
593 return napi_ok;
594 };
595 auto output = [context](napi_env env, napi_value *result) -> napi_status {
596 napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
597 return napi_ok;
598 };
599 auto exec = [context](AsyncCall::Context *ctx) {
600 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
601 OHOS::Uri uri(context->uri);
602 Uri uriValue = context->proxy->datashareHelper_->DenormalizeUri(uri);
603 context->resultString = uriValue.ToString();
604 context->status = napi_ok;
605 } else {
606 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
607 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
608 }
609 };
610 context->SetAction(std::move(input), std::move(output));
611 AsyncCall asyncCall(env, info, context);
612 return asyncCall.Call(env, exec);
613 }
614
Napi_NotifyChange(napi_env env,napi_callback_info info)615 napi_value NapiDataShareHelper::Napi_NotifyChange(napi_env env, napi_callback_info info)
616 {
617 LOG_DEBUG("Start");
618 auto context = std::make_shared<ContextInfo>();
619 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
620 NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
621 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
622
623 GetUri(env, argv[PARAM0], context->uri);
624 return napi_ok;
625 };
626 auto output = [context](napi_env env, napi_value *result) -> napi_status {
627 napi_get_null(env, result);
628 return napi_ok;
629 };
630 auto exec = [context](AsyncCall::Context *ctx) {
631 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
632 OHOS::Uri uri(context->uri);
633 context->proxy->datashareHelper_->NotifyChange(uri);
634 context->status = napi_ok;
635 } else {
636 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
637 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
638 }
639 };
640 context->SetAction(std::move(input), std::move(output));
641 AsyncCall asyncCall(env, info, context);
642 return asyncCall.Call(env, exec);
643 }
644
Napi_On(napi_env env,napi_callback_info info)645 napi_value NapiDataShareHelper::Napi_On(napi_env env, napi_callback_info info)
646 {
647 LOG_DEBUG("Start");
648 napi_value self = nullptr;
649 size_t argc = MAX_ARGC;
650 napi_value argv[MAX_ARGC] = {nullptr};
651 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
652 NAPI_ASSERT(env, argc == ARGS_THREE, "wrong count of args");
653
654 NapiDataShareHelper *proxy = nullptr;
655 NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), nullptr);
656 NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
657 NAPI_ASSERT_BASE(env, proxy->datashareHelper_ != nullptr, "there is no DataShareHelper instance", nullptr);
658
659 napi_valuetype valueType;
660 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
661 if (valueType != napi_string) {
662 LOG_ERROR("type is not string");
663 return nullptr;
664 }
665 std::string type = DataShareJSUtils::Convert2String(env, argv[PARAM0]);
666 if (type != "dataChange") {
667 LOG_ERROR("wrong register type : %{public}s", type.c_str());
668 return nullptr;
669 }
670
671 NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType));
672 NAPI_ASSERT_BASE(env, valueType == napi_string, "uri is not string", nullptr);
673 std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
674
675 NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
676 NAPI_ASSERT_BASE(env, valueType == napi_function, "callback is not a function", nullptr);
677
678 proxy->RegisteredObserver(env, uri, argv[PARAM2]);
679 return nullptr;
680 }
681
Napi_Off(napi_env env,napi_callback_info info)682 napi_value NapiDataShareHelper::Napi_Off(napi_env env, napi_callback_info info)
683 {
684 LOG_DEBUG("Start");
685 napi_value self = nullptr;
686 size_t argc = MAX_ARGC;
687 napi_value argv[MAX_ARGC] = {nullptr};
688 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
689 NAPI_ASSERT(env, argc == ARGS_TWO || argc == ARGS_THREE, "wrong count of args");
690
691 NapiDataShareHelper *proxy = nullptr;
692 NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), nullptr);
693 NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
694 NAPI_ASSERT_BASE(env, proxy->datashareHelper_ != nullptr, "there is no DataShareHelper instance", nullptr);
695
696 napi_valuetype valueType;
697 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
698 if (valueType != napi_string) {
699 LOG_ERROR("type is not string");
700 return nullptr;
701 }
702 std::string type = DataShareJSUtils::Convert2String(env, argv[PARAM0]);
703 if (type != "dataChange") {
704 LOG_ERROR("wrong register type : %{public}s", type.c_str());
705 return nullptr;
706 }
707
708 NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType));
709 NAPI_ASSERT_BASE(env, valueType == napi_string, "uri is not string", nullptr);
710 std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
711
712 if (argc == ARGS_THREE) {
713 NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
714 NAPI_ASSERT_BASE(env, valueType == napi_function, "callback is not a function", nullptr);
715 proxy->UnRegisteredObserver(env, uri, argv[PARAM2]);
716 return nullptr;
717 }
718 proxy->UnRegisteredObserver(env, uri);
719 return nullptr;
720 }
721
HasRegisteredObserver(napi_env env,std::list<sptr<NAPIDataShareObserver>> & list,napi_value callback)722 bool NapiDataShareHelper::HasRegisteredObserver(napi_env env, std::list<sptr<NAPIDataShareObserver>> &list,
723 napi_value callback)
724 {
725 for (auto &it : list) {
726 if (DataShareJSUtils::Equals(env, callback, it->observer_->GetCallback())) {
727 LOG_DEBUG("The observer has already subscribed.");
728 return true;
729 }
730 }
731 return false;
732 }
733
RegisteredObserver(napi_env env,const std::string & uri,napi_value callback)734 void NapiDataShareHelper::RegisteredObserver(napi_env env, const std::string &uri, napi_value callback)
735 {
736 std::lock_guard<std::mutex> lck(listMutex_);
737 observerMap_.try_emplace(uri);
738
739 auto &list = observerMap_.find(uri)->second;
740 if (HasRegisteredObserver(env, list, callback)) {
741 LOG_DEBUG("has registered observer");
742 return;
743 }
744 auto innerObserver = std::make_shared<NAPIInnerObserver>(env, callback);
745 sptr<NAPIDataShareObserver> observer(new (std::nothrow) NAPIDataShareObserver(innerObserver));
746 if (observer == nullptr) {
747 LOG_ERROR("observer is nullptr");
748 return;
749 }
750 datashareHelper_->RegisterObserver(Uri(uri), observer);
751 list.push_back(observer);
752 }
753
UnRegisteredObserver(napi_env env,const std::string & uri,napi_value callback)754 void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string &uri, napi_value callback)
755 {
756 std::lock_guard<std::mutex> lck(listMutex_);
757 auto obs = observerMap_.find(uri);
758 if (obs == observerMap_.end()) {
759 LOG_DEBUG("this uri hasn't been registered");
760 return;
761 }
762 auto &list = obs->second;
763 auto it = list.begin();
764 while (it != list.end()) {
765 if (!DataShareJSUtils::Equals(env, callback, (*it)->observer_->GetCallback())) {
766 ++it;
767 continue;
768 }
769 datashareHelper_->UnregisterObserver(Uri(uri), *it);
770 (*it)->observer_->DeleteReference();
771 it = list.erase(it);
772 break;
773 }
774 if (list.empty()) {
775 observerMap_.erase(uri);
776 }
777 }
778
UnRegisteredObserver(napi_env env,const std::string & uri)779 void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string &uri)
780 {
781 std::lock_guard<std::mutex> lck(listMutex_);
782 auto obs = observerMap_.find(uri);
783 if (obs == observerMap_.end()) {
784 LOG_DEBUG("this uri hasn't been registered");
785 return;
786 }
787 auto &list = obs->second;
788 auto it = list.begin();
789 while (it != list.end()) {
790 datashareHelper_->UnregisterObserver(Uri(uri), *it);
791 (*it)->observer_->DeleteReference();
792 it = list.erase(it);
793 }
794 observerMap_.erase(uri);
795 }
796 } // namespace DataShare
797 } // namespace OHOS