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 };
208 if (napi_wrap(env, self, proxy, finalize, nullptr, nullptr) != napi_ok) {
209 finalize(env, proxy, nullptr);
210 return nullptr;
211 }
212 return self;
213 }
214
Napi_OpenFile(napi_env env,napi_callback_info info)215 napi_value NapiDataShareHelper::Napi_OpenFile(napi_env env, napi_callback_info info)
216 {
217 LOG_DEBUG("Start");
218 auto context = std::make_shared<ContextInfo>();
219 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
220 NAPI_ASSERT_BASE(env, argc == 2 || argc == 3, " should 2 or 3 parameters!", napi_invalid_arg);
221 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
222
223 GetUri(env, argv[PARAM0], context->uri);
224
225 napi_valuetype valuetype = napi_undefined;
226 napi_typeof(env, argv[PARAM1], &valuetype);
227 if (valuetype == napi_string) {
228 context->mode = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
229 } else {
230 LOG_ERROR("wrong type, should be napi_string");
231 }
232 return napi_ok;
233 };
234 auto output = [context](napi_env env, napi_value *result) -> napi_status {
235 napi_create_int32(env, context->resultNumber, result);
236 return napi_ok;
237 };
238 auto exec = [context](AsyncCall::Context *ctx) {
239 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
240 OHOS::Uri uri(context->uri);
241 context->resultNumber = context->proxy->datashareHelper_->OpenFile(uri, context->mode);
242 context->status = napi_ok;
243 } else {
244 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
245 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
246 }
247 };
248 context->SetAction(std::move(input), std::move(output));
249 AsyncCall asyncCall(env, info, context);
250 return asyncCall.Call(env, exec);
251 }
252
Napi_Insert(napi_env env,napi_callback_info info)253 napi_value NapiDataShareHelper::Napi_Insert(napi_env env, napi_callback_info info)
254 {
255 LOG_DEBUG("Start");
256 auto context = std::make_shared<ContextInfo>();
257 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
258 if (argc != 2 && argc != 3) {
259 context->error = std::make_shared<ParametersNumError>("2 or 3");
260 return napi_invalid_arg;
261 }
262 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
263
264 if (!GetUri(env, argv[PARAM0], context->uri)) {
265 context->error = std::make_shared<ParametersTypeError>("uri", "string");
266 return napi_invalid_arg;
267 }
268
269 context->valueBucket.Clear();
270 if (!GetValueBucketObject(context->valueBucket, env, argv[PARAM1])) {
271 context->error = std::make_shared<ParametersTypeError>("valueBucket",
272 "[string|number|boolean|null|Uint8Array]");
273 return napi_invalid_arg;
274 }
275
276 return napi_ok;
277 };
278 auto output = [context](napi_env env, napi_value *result) -> napi_status {
279 if (context->resultNumber < 0) {
280 context->error = std::make_shared<InnerError>();
281 return napi_generic_failure;
282 }
283 napi_create_int32(env, context->resultNumber, result);
284 return napi_ok;
285 };
286 auto exec = [context](AsyncCall::Context *ctx) {
287 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
288 OHOS::Uri uri(context->uri);
289 context->resultNumber = context->proxy->datashareHelper_->Insert(uri, context->valueBucket);
290 context->status = napi_ok;
291 } else {
292 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
293 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
294 }
295 };
296 context->SetAction(std::move(input), std::move(output));
297 AsyncCall asyncCall(env, info, context);
298 return asyncCall.Call(env, exec);
299 }
300
Napi_Delete(napi_env env,napi_callback_info info)301 napi_value NapiDataShareHelper::Napi_Delete(napi_env env, napi_callback_info info)
302 {
303 LOG_DEBUG("Start");
304 auto context = std::make_shared<ContextInfo>();
305 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
306 if (argc != 2 && argc != 3) {
307 context->error = std::make_shared<ParametersNumError>("2 or 3");
308 return napi_invalid_arg;
309 }
310 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
311
312 if (!GetUri(env, argv[PARAM0], context->uri)) {
313 context->error = std::make_shared<ParametersTypeError>("uri", "string");
314 return napi_invalid_arg;
315 }
316
317 context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
318 return napi_ok;
319 };
320 auto output = [context](napi_env env, napi_value *result) -> napi_status {
321 if (context->resultNumber < 0) {
322 context->error = std::make_shared<InnerError>();
323 return napi_generic_failure;
324 }
325 napi_create_int32(env, context->resultNumber, result);
326 return napi_ok;
327 };
328 auto exec = [context](AsyncCall::Context *ctx) {
329 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
330 OHOS::Uri uri(context->uri);
331 context->resultNumber = context->proxy->datashareHelper_->Delete(uri, context->predicates);
332 context->status = napi_ok;
333 } else {
334 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
335 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
336 }
337 };
338 context->SetAction(std::move(input), std::move(output));
339 AsyncCall asyncCall(env, info, context);
340 return asyncCall.Call(env, exec);
341 }
342
Napi_Query(napi_env env,napi_callback_info info)343 napi_value NapiDataShareHelper::Napi_Query(napi_env env, napi_callback_info info)
344 {
345 LOG_DEBUG("Start");
346 auto context = std::make_shared<ContextInfo>();
347 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
348 if (argc != 3 && argc != 4) {
349 context->error = std::make_shared<ParametersNumError>("3 or 4");
350 return napi_invalid_arg;
351 }
352 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
353
354 if (!GetUri(env, argv[PARAM0], context->uri)) {
355 context->error = std::make_shared<ParametersTypeError>("uri", "string");
356 return napi_invalid_arg;
357 }
358
359 context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
360
361 context->columns = DataShareJSUtils::Convert2StrVector(env, argv[PARAM2], DataShareJSUtils::DEFAULT_BUF_SIZE);
362 return napi_ok;
363 };
364 auto output = [context](napi_env env, napi_value *result) -> napi_status {
365 if (context->resultObject == nullptr) {
366 context->error = std::make_shared<InnerError>();
367 return napi_generic_failure;
368 }
369 *result = DataShareResultSetProxy::NewInstance(env, context->resultObject);
370 return napi_ok;
371 };
372 auto exec = [context](AsyncCall::Context *ctx) {
373 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
374 OHOS::Uri uri(context->uri);
375 context->resultObject = context->proxy->datashareHelper_->Query(uri, context->predicates, context->columns);
376 context->status = napi_ok;
377 } else {
378 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
379 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
380 }
381 };
382 context->SetAction(std::move(input), std::move(output));
383 AsyncCall asyncCall(env, info, context);
384 return asyncCall.Call(env, exec);
385 }
386
Napi_Update(napi_env env,napi_callback_info info)387 napi_value NapiDataShareHelper::Napi_Update(napi_env env, napi_callback_info info)
388 {
389 LOG_DEBUG("Start");
390 auto context = std::make_shared<ContextInfo>();
391 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
392 if (argc != 3 && argc != 4) {
393 context->error = std::make_shared<ParametersNumError>("3 or 4");
394 return napi_invalid_arg;
395 }
396 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
397
398 if (!GetUri(env, argv[PARAM0], context->uri)) {
399 context->error = std::make_shared<ParametersTypeError>("uri", "string");
400 return napi_invalid_arg;
401 }
402
403 context->predicates = UnwrapDataSharePredicates(env, argv[PARAM1]);
404
405 context->valueBucket.Clear();
406 if (!GetValueBucketObject(context->valueBucket, env, argv[PARAM2])) {
407 context->error = std::make_shared<ParametersTypeError>("valueBucket",
408 "[string|number|boolean|null|Uint8Array]");
409 return napi_invalid_arg;
410 }
411 return napi_ok;
412 };
413 auto output = [context](napi_env env, napi_value *result) -> napi_status {
414 if (context->resultNumber < 0) {
415 context->error = std::make_shared<InnerError>();
416 return napi_generic_failure;
417 }
418 napi_create_int32(env, context->resultNumber, result);
419 return napi_ok;
420 };
421 auto exec = [context](AsyncCall::Context *ctx) {
422 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
423 OHOS::Uri uri(context->uri);
424 context->resultNumber =
425 context->proxy->datashareHelper_->Update(uri, context->predicates, context->valueBucket);
426 context->status = napi_ok;
427 } else {
428 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
429 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
430 }
431 };
432 context->SetAction(std::move(input), std::move(output));
433 AsyncCall asyncCall(env, info, context);
434 return asyncCall.Call(env, exec);
435 }
436
Napi_BatchInsert(napi_env env,napi_callback_info info)437 napi_value NapiDataShareHelper::Napi_BatchInsert(napi_env env, napi_callback_info info)
438 {
439 LOG_DEBUG("Start");
440 auto context = std::make_shared<ContextInfo>();
441 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
442 if (argc != 2 && argc != 3) {
443 context->error = std::make_shared<ParametersNumError>("2 or 3");
444 return napi_invalid_arg;
445 }
446 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
447
448 if (!GetUri(env, argv[PARAM0], context->uri)) {
449 context->error = std::make_shared<ParametersTypeError>("uri", "string");
450 return napi_invalid_arg;
451 }
452 bool status = false;
453 context->values = GetValuesBucketArray(env, argv[PARAM1], status);
454 if (!status) {
455 context->error = std::make_shared<ParametersTypeError>("valueBucket",
456 "[string|number|boolean|null|Uint8Array]");
457 return napi_invalid_arg;
458 }
459 return napi_ok;
460 };
461 auto output = [context](napi_env env, napi_value *result) -> napi_status {
462 if (context->resultNumber < 0) {
463 context->error = std::make_shared<InnerError>();
464 return napi_generic_failure;
465 }
466 napi_create_int32(env, context->resultNumber, result);
467 return napi_ok;
468 };
469 auto exec = [context](AsyncCall::Context *ctx) {
470 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
471 OHOS::Uri uri(context->uri);
472 context->resultNumber = context->proxy->datashareHelper_->BatchInsert(uri, context->values);
473 context->status = napi_ok;
474 } else {
475 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
476 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
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_GetType(napi_env env,napi_callback_info info)484 napi_value NapiDataShareHelper::Napi_GetType(napi_env env, napi_callback_info info)
485 {
486 LOG_DEBUG("Start");
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 NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
490 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
491
492 GetUri(env, argv[PARAM0], context->uri);
493 return napi_ok;
494 };
495 auto output = [context](napi_env env, napi_value *result) -> napi_status {
496 napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
497 return napi_ok;
498 };
499 auto exec = [context](AsyncCall::Context *ctx) {
500 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
501 OHOS::Uri uri(context->uri);
502 context->resultString = context->proxy->datashareHelper_->GetType(uri);
503 context->status = napi_ok;
504 } else {
505 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
506 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
507 }
508 };
509 context->SetAction(std::move(input), std::move(output));
510 AsyncCall asyncCall(env, info, context);
511 return asyncCall.Call(env, exec);
512 }
513
Napi_GetFileTypes(napi_env env,napi_callback_info info)514 napi_value NapiDataShareHelper::Napi_GetFileTypes(napi_env env, napi_callback_info info)
515 {
516 LOG_DEBUG("Start");
517 auto context = std::make_shared<ContextInfo>();
518 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
519 NAPI_ASSERT_BASE(env, argc == 2 || argc == 3, " should 2 or 3 parameters!", napi_invalid_arg);
520 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
521
522 GetUri(env, argv[PARAM0], context->uri);
523
524 napi_valuetype valuetype = napi_undefined;
525 napi_typeof(env, argv[PARAM1], &valuetype);
526 if (valuetype == napi_string) {
527 context->mimeTypeFilter = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
528 } else {
529 LOG_ERROR("wrong type, should be napi_string");
530 }
531 return napi_ok;
532 };
533 auto output = [context](napi_env env, napi_value *result) -> napi_status {
534 *result = DataShareJSUtils::Convert2JSValue(env, context->resultStrArr);
535 return napi_ok;
536 };
537 auto exec = [context](AsyncCall::Context *ctx) {
538 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
539 OHOS::Uri uri(context->uri);
540 context->resultStrArr = context->proxy->datashareHelper_->GetFileTypes(uri, context->mimeTypeFilter);
541 context->status = napi_ok;
542 } else {
543 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
544 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
545 }
546 };
547 context->SetAction(std::move(input), std::move(output));
548 AsyncCall asyncCall(env, info, context);
549 return asyncCall.Call(env, exec);
550 }
551
Napi_NormalizeUri(napi_env env,napi_callback_info info)552 napi_value NapiDataShareHelper::Napi_NormalizeUri(napi_env env, napi_callback_info info)
553 {
554 LOG_DEBUG("Start");
555 auto context = std::make_shared<ContextInfo>();
556 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
557 NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
558 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
559
560 GetUri(env, argv[PARAM0], context->uri);
561 return napi_ok;
562 };
563 auto output = [context](napi_env env, napi_value *result) -> napi_status {
564 napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
565 return napi_ok;
566 };
567 auto exec = [context](AsyncCall::Context *ctx) {
568 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
569 OHOS::Uri uri(context->uri);
570 Uri uriValue = context->proxy->datashareHelper_->NormalizeUri(uri);
571 context->resultString = uriValue.ToString();
572 context->status = napi_ok;
573 } else {
574 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
575 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
576 }
577 };
578 context->SetAction(std::move(input), std::move(output));
579 AsyncCall asyncCall(env, info, context);
580 return asyncCall.Call(env, exec);
581 }
582
Napi_DenormalizeUri(napi_env env,napi_callback_info info)583 napi_value NapiDataShareHelper::Napi_DenormalizeUri(napi_env env, napi_callback_info info)
584 {
585 LOG_DEBUG("Start");
586 auto context = std::make_shared<ContextInfo>();
587 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
588 NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
589 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
590
591 GetUri(env, argv[PARAM0], context->uri);
592 return napi_ok;
593 };
594 auto output = [context](napi_env env, napi_value *result) -> napi_status {
595 napi_create_string_utf8(env, context->resultString.c_str(), NAPI_AUTO_LENGTH, result);
596 return napi_ok;
597 };
598 auto exec = [context](AsyncCall::Context *ctx) {
599 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
600 OHOS::Uri uri(context->uri);
601 Uri uriValue = context->proxy->datashareHelper_->DenormalizeUri(uri);
602 context->resultString = uriValue.ToString();
603 context->status = napi_ok;
604 } else {
605 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
606 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
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_NotifyChange(napi_env env,napi_callback_info info)614 napi_value NapiDataShareHelper::Napi_NotifyChange(napi_env env, napi_callback_info info)
615 {
616 LOG_DEBUG("Start");
617 auto context = std::make_shared<ContextInfo>();
618 auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
619 NAPI_ASSERT_BASE(env, argc == 1 || argc == 2, " should 1 or 2 parameters!", napi_invalid_arg);
620 LOG_DEBUG("argc : %{public}d", static_cast<int>(argc));
621
622 GetUri(env, argv[PARAM0], context->uri);
623 return napi_ok;
624 };
625 auto output = [context](napi_env env, napi_value *result) -> napi_status {
626 napi_get_null(env, result);
627 return napi_ok;
628 };
629 auto exec = [context](AsyncCall::Context *ctx) {
630 if (context->proxy->datashareHelper_ != nullptr && !context->uri.empty()) {
631 OHOS::Uri uri(context->uri);
632 context->proxy->datashareHelper_->NotifyChange(uri);
633 context->status = napi_ok;
634 } else {
635 LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->uri is empty : %{public}d",
636 context->proxy->datashareHelper_ == nullptr, context->uri.empty());
637 }
638 };
639 context->SetAction(std::move(input), std::move(output));
640 AsyncCall asyncCall(env, info, context);
641 return asyncCall.Call(env, exec);
642 }
643
Napi_On(napi_env env,napi_callback_info info)644 napi_value NapiDataShareHelper::Napi_On(napi_env env, napi_callback_info info)
645 {
646 LOG_DEBUG("Start");
647 napi_value self = nullptr;
648 size_t argc = MAX_ARGC;
649 napi_value argv[MAX_ARGC] = {nullptr};
650 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
651 NAPI_ASSERT(env, argc == ARGS_THREE, "wrong count of args");
652
653 NapiDataShareHelper *proxy = nullptr;
654 NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), nullptr);
655 NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
656 NAPI_ASSERT_BASE(env, proxy->datashareHelper_ != nullptr, "there is no DataShareHelper instance", nullptr);
657
658 napi_valuetype valueType;
659 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
660 if (valueType != napi_string) {
661 LOG_ERROR("type is not string");
662 return nullptr;
663 }
664 std::string type = DataShareJSUtils::Convert2String(env, argv[PARAM0]);
665 if (type != "dataChange") {
666 LOG_ERROR("wrong register type : %{public}s", type.c_str());
667 return nullptr;
668 }
669
670 NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType));
671 NAPI_ASSERT_BASE(env, valueType == napi_string, "uri is not string", nullptr);
672 std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
673
674 NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
675 NAPI_ASSERT_BASE(env, valueType == napi_function, "callback is not a function", nullptr);
676
677 proxy->RegisteredObserver(env, uri, argv[PARAM2]);
678 return nullptr;
679 }
680
Napi_Off(napi_env env,napi_callback_info info)681 napi_value NapiDataShareHelper::Napi_Off(napi_env env, napi_callback_info info)
682 {
683 LOG_DEBUG("Start");
684 napi_value self = nullptr;
685 size_t argc = MAX_ARGC;
686 napi_value argv[MAX_ARGC] = {nullptr};
687 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
688 NAPI_ASSERT(env, argc == ARGS_TWO || argc == ARGS_THREE, "wrong count of args");
689
690 NapiDataShareHelper *proxy = nullptr;
691 NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast<void **>(&proxy)), nullptr);
692 NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataShareHelper instance", nullptr);
693 NAPI_ASSERT_BASE(env, proxy->datashareHelper_ != nullptr, "there is no DataShareHelper instance", nullptr);
694
695 napi_valuetype valueType;
696 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
697 if (valueType != napi_string) {
698 LOG_ERROR("type is not string");
699 return nullptr;
700 }
701 std::string type = DataShareJSUtils::Convert2String(env, argv[PARAM0]);
702 if (type != "dataChange") {
703 LOG_ERROR("wrong register type : %{public}s", type.c_str());
704 return nullptr;
705 }
706
707 NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType));
708 NAPI_ASSERT_BASE(env, valueType == napi_string, "uri is not string", nullptr);
709 std::string uri = DataShareJSUtils::Convert2String(env, argv[PARAM1]);
710
711 if (argc == ARGS_THREE) {
712 NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType));
713 NAPI_ASSERT_BASE(env, valueType == napi_function, "callback is not a function", nullptr);
714 proxy->UnRegisteredObserver(env, uri, argv[PARAM2]);
715 return nullptr;
716 }
717 proxy->UnRegisteredObserver(env, uri);
718 return nullptr;
719 }
720
HasRegisteredObserver(napi_env env,std::list<sptr<NAPIDataShareObserver>> & list,napi_value callback)721 bool NapiDataShareHelper::HasRegisteredObserver(napi_env env, std::list<sptr<NAPIDataShareObserver>> &list,
722 napi_value callback)
723 {
724 for (auto &it : list) {
725 if (DataShareJSUtils::Equals(env, callback, it->observer_->GetCallback())) {
726 LOG_DEBUG("The observer has already subscribed.");
727 return true;
728 }
729 }
730 return false;
731 }
732
RegisteredObserver(napi_env env,const std::string & uri,napi_value callback)733 void NapiDataShareHelper::RegisteredObserver(napi_env env, const std::string &uri, napi_value callback)
734 {
735 std::lock_guard<std::mutex> lck(listMutex_);
736 observerMap_.try_emplace(uri);
737
738 auto &list = observerMap_.find(uri)->second;
739 if (HasRegisteredObserver(env, list, callback)) {
740 LOG_DEBUG("has registered observer");
741 return;
742 }
743 auto innerObserver = std::make_shared<NAPIInnerObserver>(env, callback);
744 sptr<NAPIDataShareObserver> observer(new (std::nothrow) NAPIDataShareObserver(innerObserver));
745 if (observer == nullptr) {
746 LOG_ERROR("observer is nullptr");
747 return;
748 }
749 datashareHelper_->RegisterObserver(Uri(uri), observer);
750 list.push_back(observer);
751 }
752
UnRegisteredObserver(napi_env env,const std::string & uri,napi_value callback)753 void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string &uri, napi_value callback)
754 {
755 std::lock_guard<std::mutex> lck(listMutex_);
756 auto obs = observerMap_.find(uri);
757 if (obs == observerMap_.end()) {
758 LOG_DEBUG("this uri hasn't been registered");
759 return;
760 }
761 auto &list = obs->second;
762 auto it = list.begin();
763 while (it != list.end()) {
764 if (!DataShareJSUtils::Equals(env, callback, (*it)->observer_->GetCallback())) {
765 ++it;
766 continue;
767 }
768 datashareHelper_->UnregisterObserver(Uri(uri), *it);
769 (*it)->observer_->DeleteReference();
770 it = list.erase(it);
771 break;
772 }
773 if (list.empty()) {
774 observerMap_.erase(uri);
775 }
776 }
777
UnRegisteredObserver(napi_env env,const std::string & uri)778 void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string &uri)
779 {
780 std::lock_guard<std::mutex> lck(listMutex_);
781 auto obs = observerMap_.find(uri);
782 if (obs == observerMap_.end()) {
783 LOG_DEBUG("this uri hasn't been registered");
784 return;
785 }
786 auto &list = obs->second;
787 auto it = list.begin();
788 while (it != list.end()) {
789 datashareHelper_->UnregisterObserver(Uri(uri), *it);
790 (*it)->observer_->DeleteReference();
791 it = list.erase(it);
792 }
793 observerMap_.erase(uri);
794 }
795 } // namespace DataShare
796 } // namespace OHOS