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 "js_datashare_ext_ability.h"
17
18 #include "ability_info.h"
19 #include "dataobs_mgr_client.h"
20 #include "datashare_log.h"
21 #include "datashare_predicates_proxy.h"
22 #include "datashare_stub_impl.h"
23 #include "ikvstore_data_service.h"
24 #include "idata_share_service.h"
25 #include "iservice_registry.h"
26 #include "js_datashare_ext_ability_context.h"
27 #include "js_proxy.h"
28 #include "js_runtime.h"
29 #include "js_runtime_utils.h"
30 #include "napi_common_util.h"
31 #include "napi_common_want.h"
32 #include "napi_datashare_values_bucket.h"
33 #include "napi_remote_object.h"
34 #include "system_ability_definition.h"
35
36 using namespace OHOS::DistributedShare::DataShare;
37
38 namespace OHOS {
39 namespace DataShare {
40 using namespace AbilityRuntime;
41 namespace {
42 constexpr int INVALID_VALUE = -1;
43 static constexpr int32_t MAX_ARGC = 6;
44 static constexpr int32_t MIN_ARGC = 2;
45 constexpr const char ASYNC_CALLBACK_NAME[] = "AsyncCallback";
46 constexpr int CALLBACK_LENGTH = sizeof(ASYNC_CALLBACK_NAME) - 1;
47 }
48
49 bool MakeNapiColumn(napi_env env, napi_value &napiColumns, const std::vector<std::string> &columns);
50
51 using namespace OHOS::AppExecFwk;
52 using DataObsMgrClient = OHOS::AAFwk::DataObsMgrClient;
53
Create(const std::unique_ptr<Runtime> & runtime)54 JsDataShareExtAbility* JsDataShareExtAbility::Create(const std::unique_ptr<Runtime>& runtime)
55 {
56 return new JsDataShareExtAbility(static_cast<JsRuntime&>(*runtime));
57 }
58
JsDataShareExtAbility(JsRuntime & jsRuntime)59 JsDataShareExtAbility::JsDataShareExtAbility(JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
60
~JsDataShareExtAbility()61 JsDataShareExtAbility::~JsDataShareExtAbility()
62 {
63 LOG_DEBUG("Js datashare extension destructor.");
64 jsRuntime_.FreeNativeReference(std::move(jsObj_));
65 }
66
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)67 void JsDataShareExtAbility::Init(const std::shared_ptr<AbilityLocalRecord> &record,
68 const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
69 const sptr<IRemoteObject> &token)
70 {
71 DataShareExtAbility::Init(record, application, handler, token);
72 std::string srcPath = "";
73 GetSrcPath(srcPath);
74 if (srcPath.empty()) {
75 LOG_ERROR("Failed to get srcPath");
76 return;
77 }
78
79 std::string moduleName(Extension::abilityInfo_->moduleName);
80 moduleName.append("::").append(abilityInfo_->name);
81 LOG_DEBUG("module:%{public}s, srcPath:%{public}s.", moduleName.c_str(), srcPath.c_str());
82 HandleScope handleScope(jsRuntime_);
83 napi_env env = jsRuntime_.GetNapiEnv();
84
85 jsObj_ = jsRuntime_.LoadModule(
86 moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == CompileMode::ES_MODULE);
87 if (jsObj_ == nullptr) {
88 LOG_ERROR("Failed to get jsObj_, moduleName:%{public}s.", moduleName.c_str());
89 return;
90 }
91 napi_value obj = jsObj_->GetNapiValue();
92 if (obj == nullptr) {
93 LOG_ERROR("Failed to get JsDataShareExtAbility object, moduleName:%{public}s.", moduleName.c_str());
94 return;
95 }
96
97 auto context = GetContext();
98 if (context == nullptr) {
99 LOG_ERROR("Failed to get context, moduleName:%{public}s.", moduleName.c_str());
100 return;
101 }
102 napi_value contextObj = CreateJsDataShareExtAbilityContext(env, context);
103 auto contextRef = jsRuntime_.LoadSystemModule("application.DataShareExtensionAbilityContext", &contextObj, 1);
104 if (contextRef == nullptr) {
105 LOG_ERROR("Failed to get contextRef");
106 return;
107 }
108 contextObj = contextRef->GetNapiValue();
109 context->Bind(jsRuntime_, contextRef.release());
110 napi_set_named_property(env, obj, "context", contextObj);
111 napi_wrap(env, contextObj, new std::weak_ptr<AbilityRuntime::Context>(context),
112 [](napi_env, void *data, void *) {
113 LOG_INFO("Finalizer for weak_ptr datashare extension ability context is called");
114 delete static_cast<std::weak_ptr<AbilityRuntime::Context>*>(data);
115 }, nullptr, nullptr);
116 }
117
OnStart(const AAFwk::Want & want)118 void JsDataShareExtAbility::OnStart(const AAFwk::Want &want)
119 {
120 Extension::OnStart(want);
121 HandleScope handleScope(jsRuntime_);
122 napi_env env = jsRuntime_.GetNapiEnv();
123 napi_handle_scope scope = nullptr;
124 napi_open_handle_scope(env, &scope);
125 if (scope == nullptr) {
126 return;
127 }
128 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
129 napi_value argv[] = {napiWant};
130 std::shared_ptr<AsyncContext> context = std::make_shared<AsyncContext>();
131 context->isNeedNotify_ = true;
132 CallObjectMethod("onCreate", argv, sizeof(argv)/sizeof(argv[0]), context);
133 napi_close_handle_scope(env, scope);
134 }
135
OnConnect(const AAFwk::Want & want)136 sptr<IRemoteObject> JsDataShareExtAbility::OnConnect(const AAFwk::Want &want)
137 {
138 Extension::OnConnect(want);
139 sptr<DataShareStubImpl> remoteObject = new (std::nothrow) DataShareStubImpl(
140 std::static_pointer_cast<JsDataShareExtAbility>(shared_from_this()),
141 jsRuntime_.GetNapiEnv());
142 if (remoteObject == nullptr) {
143 LOG_ERROR("No memory allocated for DataShareStubImpl");
144 return nullptr;
145 }
146 return remoteObject->AsObject();
147 }
148
UnwrapBatchUpdateResult(napi_env env,napi_value & info,std::vector<BatchUpdateResult> & results)149 bool JsDataShareExtAbility::UnwrapBatchUpdateResult(napi_env env, napi_value &info,
150 std::vector<BatchUpdateResult> &results)
151 {
152 napi_value keys = 0;
153 if (napi_get_property_names(env, info, &keys) != napi_ok) {
154 LOG_ERROR("napi_get_property_names failed");
155 return false;
156 }
157
158 uint32_t arrLen = 0;
159 if (napi_get_array_length(env, keys, &arrLen) != napi_ok) {
160 LOG_ERROR("napi_get_array_length failed");
161 return false;
162 }
163 for (size_t i = 0; i < arrLen; i++) {
164 napi_value key = 0;
165 if (napi_get_element(env, keys, i, &key) != napi_ok) {
166 LOG_ERROR("napi_get_element failed");
167 return false;
168 }
169 BatchUpdateResult batchUpdateResult;
170 batchUpdateResult.uri = DataShareJSUtils::UnwrapStringFromJS(env, key);
171 napi_value value = 0;
172 if (napi_get_property(env, info, key, &value) != napi_ok) {
173 LOG_ERROR("napi_get_property failed");
174 return false;
175 }
176 if (!UnwrapArrayInt32FromJS(env, value, batchUpdateResult.codes)) {
177 LOG_ERROR("UnwrapArrayInt32FromJS failed");
178 return false;
179 }
180 results.push_back(std::move(batchUpdateResult));
181 }
182 return true;
183 }
184
CheckAndSetAsyncResult(napi_env env)185 void JsDataShareExtAbility::CheckAndSetAsyncResult(napi_env env)
186 {
187 napi_valuetype type = napi_undefined;
188 auto result = GetAsyncResult();
189 napi_typeof(env, result, &type);
190 if (type == napi_valuetype::napi_number) {
191 int32_t value = OHOS::AppExecFwk::UnwrapInt32FromJS(env, result);
192 SetResult(value);
193 } else if (type == napi_valuetype::napi_string) {
194 std::string value = OHOS::AppExecFwk::UnwrapStringFromJS(env, result);
195 SetResult(value);
196 } else if (type == napi_valuetype::napi_object) {
197 JSProxy::JSCreator<ResultSetBridge> *proxy = nullptr;
198 napi_unwrap(env, result, reinterpret_cast<void **>(&proxy));
199 if (proxy == nullptr) {
200 std::vector<BatchUpdateResult> results;
201 if (UnwrapBatchUpdateResult(env, result, results)) {
202 SetResult(results);
203 return;
204 }
205 std::vector<std::string> value;
206 OHOS::AppExecFwk::UnwrapArrayStringFromJS(env, result, value);
207 SetResult(value);
208 } else {
209 std::shared_ptr<ResultSetBridge> value = proxy->Create();
210 std::shared_ptr<DataShareResultSet> resultSet = std::make_shared<DataShareResultSet>(value);
211 SetResultSet(resultSet);
212 }
213 } else {
214 callbackResultNumber_ = -1;
215 callbackResultString_ = "";
216 callbackResultStringArr_ = {};
217 SetResultSet(nullptr);
218 }
219 }
220
AsyncCallback(napi_env env,napi_callback_info info)221 napi_value JsDataShareExtAbility::AsyncCallback(napi_env env, napi_callback_info info)
222 {
223 if (env == nullptr || info == nullptr) {
224 LOG_ERROR("invalid param.");
225 return nullptr;
226 }
227 napi_value self = nullptr;
228 size_t argc = MAX_ARGC;
229 napi_value argv[MAX_ARGC] = { nullptr };
230 void* data = nullptr;
231 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, &data));
232 if (argc < MIN_ARGC || argv[0] == nullptr || argv[1] == nullptr) {
233 LOG_ERROR("invalid args, argc : %{public}zu.", argc);
234 return CreateJsUndefined(env);
235 }
236 if (data == nullptr) {
237 LOG_ERROR("invalid object.");
238 return CreateJsUndefined(env);
239 }
240
241 AsyncCallBackPoint* point = static_cast<AsyncCallBackPoint*>(data);
242 auto instance = point->extAbility.lock();
243 if (!instance) {
244 LOG_ERROR("extension ability has been destroyed.");
245 return CreateJsUndefined(env);
246 }
247 DatashareBusinessError businessError;
248 napi_valuetype type = napi_undefined;
249 napi_typeof(env, argv[0], &type);
250 if (type == napi_valuetype::napi_object) {
251 LOG_INFO("Error in callback");
252 UnWrapBusinessError(env, argv[0], businessError);
253 }
254 if (instance != nullptr) {
255 instance->SetBusinessError(businessError);
256 instance->SetAsyncResult(argv[1]);
257 instance->CheckAndSetAsyncResult(env);
258 instance->SetRecvReply(true);
259 }
260 return CreateJsUndefined(env);
261 }
262
AsyncCallbackWithContext(napi_env env,napi_callback_info info)263 napi_value JsDataShareExtAbility::AsyncCallbackWithContext(napi_env env, napi_callback_info info)
264 {
265 if (env == nullptr || info == nullptr) {
266 LOG_ERROR("invalid param.");
267 return nullptr;
268 }
269
270 void* data = nullptr;
271 napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data);
272 if (data == nullptr) {
273 LOG_ERROR("invalid object.");
274 return CreateJsUndefined(env);
275 }
276
277 AsyncPoint* instance = static_cast<AsyncPoint*>(data);
278 if (instance != nullptr) {
279 if (instance->context->isNeedNotify_) {
280 NotifyToDataShareService();
281 }
282 }
283 return CreateJsUndefined(env);
284 }
285
CallObjectMethod(const char * name,napi_value const * argv,size_t argc,std::shared_ptr<AsyncContext> asyncContext)286 napi_value JsDataShareExtAbility::CallObjectMethod(
287 const char *name, napi_value const *argv, size_t argc, std::shared_ptr<AsyncContext> asyncContext)
288 {
289 if (!jsObj_) {
290 LOG_WARN("Not found DataShareExtAbility.js");
291 return nullptr;
292 }
293
294 HandleEscape handleEscape(jsRuntime_);
295 napi_env env = jsRuntime_.GetNapiEnv();
296 napi_value obj = jsObj_->GetNapiValue();
297 if (obj == nullptr) {
298 LOG_ERROR("Failed to get DataShareExtAbility object");
299 return nullptr;
300 }
301
302 napi_value method = nullptr;
303 napi_get_named_property(env, obj, name, &method);
304 if (method == nullptr) {
305 LOG_ERROR("Failed to get '%{public}s' from DataShareExtAbility object", name);
306 return nullptr;
307 }
308
309 AsyncPoint *point = new (std::nothrow)AsyncPoint();
310 if (point == nullptr) {
311 LOG_ERROR("JsDataShareExtAbility::CallObjectMethod new AsyncPoint error.");
312 return nullptr;
313 }
314 point->context = asyncContext;
315 size_t count = argc + 1;
316 napi_value *args = new (std::nothrow) napi_value [count];
317 if (args == nullptr) {
318 LOG_ERROR("JsDataShareExtAbility::CallObjectMethod new NapiValue error.");
319 delete point;
320 return nullptr;
321 }
322 for (size_t i = 0; i < argc; i++) {
323 args[i] = argv[i];
324 }
325
326 napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH,
327 JsDataShareExtAbility::AsyncCallbackWithContext, point, &args[argc]);
328 napi_value callResult = nullptr;
329 napi_call_function(env, obj, method, count, args, &callResult);
330 auto result = handleEscape.Escape(callResult);
331 napi_add_finalizer(env, args[argc], point,
332 [](napi_env env, void* point, void* finalize_hint) {
333 delete static_cast<AsyncPoint *>(point);
334 }, nullptr, nullptr);
335 delete []args;
336 return result;
337 }
338
CallObjectMethod(const char * name,napi_value const * argv,size_t argc,bool isAsync)339 napi_value JsDataShareExtAbility::CallObjectMethod(const char* name, napi_value const *argv,
340 size_t argc, bool isAsync)
341 {
342 if (!jsObj_) {
343 LOG_WARN("Not found DataShareExtAbility.js");
344 return nullptr;
345 }
346
347 HandleEscape handleEscape(jsRuntime_);
348 napi_env env = jsRuntime_.GetNapiEnv();
349 napi_value obj = jsObj_->GetNapiValue();
350 if (obj == nullptr) {
351 LOG_ERROR("Failed to get DataShareExtAbility object");
352 return nullptr;
353 }
354
355 napi_value method = nullptr;
356 napi_get_named_property(env, obj, name, &method);
357 if (method == nullptr) {
358 LOG_ERROR("Failed to get '%{public}s' from DataShareExtAbility object", name);
359 return nullptr;
360 }
361
362 size_t count = argc + 1;
363 napi_value *args = new (std::nothrow) napi_value[count];
364 if (args == nullptr) {
365 LOG_ERROR("JsDataShareExtAbility::CallObjectMethod new napivalue error.");
366 return nullptr;
367 }
368 for (size_t i = 0; i < argc; i++) {
369 args[i] = argv[i];
370 }
371
372 if (isAsync) {
373 auto ret = InitAsyncCallParams(argc, env, args);
374 if (ret != E_OK) {
375 LOG_ERROR("Failed to InitAsyncCallParams in isAsync.");
376 delete [] args;
377 return nullptr;
378 }
379 } else {
380 args[argc] = nullptr;
381 }
382
383 napi_value remoteNapi = nullptr;
384 NAPI_CallingInfo oldCallingInfo;
385 NAPI_RemoteObject_saveOldCallingInfo(env, oldCallingInfo);
386 SaveNewCallingInfo(env);
387 napi_status status = napi_call_function(env, obj, method, count, args, &remoteNapi);
388 NAPI_RemoteObject_resetOldCallingInfo(env, oldCallingInfo);
389 delete []args;
390 if (status != napi_ok) {
391 return nullptr;
392 }
393 return handleEscape.Escape(remoteNapi);
394 }
395
SaveNewCallingInfo(napi_env & env)396 void JsDataShareExtAbility::SaveNewCallingInfo(napi_env &env)
397 {
398 auto newCallingInfo = GetCallingInfo();
399 if (newCallingInfo == nullptr) {
400 LOG_ERROR("newCallingInfo is null.");
401 return;
402 }
403 CallingInfo callingInfo {
404 .callingPid = newCallingInfo->callingPid,
405 .callingUid = newCallingInfo->callingUid,
406 .callingTokenId = newCallingInfo->callingTokenId,
407 .activeStatus = ACTIVE_INVOKER,
408 };
409 NAPI_RemoteObject_setNewCallingInfo(env, callingInfo);
410 }
411
InitAsyncCallParams(size_t argc,napi_env & env,napi_value * args)412 int32_t JsDataShareExtAbility::InitAsyncCallParams(size_t argc, napi_env &env, napi_value *args)
413 {
414 AsyncCallBackPoint *point = new (std::nothrow)AsyncCallBackPoint();
415 if (point == nullptr) {
416 return E_ERROR;
417 }
418 callbackResultNumber_ = -1;
419 callbackResultString_ = "";
420 callbackResultStringArr_ = {};
421 SetResultSet(nullptr);
422 SetRecvReply(false);
423 point->extAbility = std::static_pointer_cast<JsDataShareExtAbility>(shared_from_this());
424 napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH,
425 JsDataShareExtAbility::AsyncCallback, point, &args[argc]);
426 napi_add_finalizer(env, args[argc], point,
427 [](napi_env env, void* point, void* finalize_hint) {
428 delete static_cast<AsyncCallBackPoint *>(point);
429 }, nullptr, nullptr);
430 return E_OK;
431 }
432
GetSrcPath(std::string & srcPath)433 void JsDataShareExtAbility::GetSrcPath(std::string &srcPath)
434 {
435 if (!Extension::abilityInfo_->isStageBasedModel) {
436 /* temporary compatibility api8 + config.json */
437 srcPath.append(Extension::abilityInfo_->package);
438 srcPath.append("/assets/js/");
439 if (!Extension::abilityInfo_->srcPath.empty()) {
440 srcPath.append(Extension::abilityInfo_->srcPath);
441 }
442 srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
443 return;
444 }
445
446 if (!Extension::abilityInfo_->srcEntrance.empty()) {
447 srcPath.append(Extension::abilityInfo_->moduleName + "/");
448 srcPath.append(Extension::abilityInfo_->srcEntrance);
449 srcPath.erase(srcPath.rfind('.'));
450 srcPath.append(".abc");
451 }
452 }
453
GetFileTypes(const Uri & uri,const std::string & mimeTypeFilter)454 std::vector<std::string> JsDataShareExtAbility::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter)
455 {
456 auto ret = DataShareExtAbility::GetFileTypes(uri, mimeTypeFilter);
457 HandleScope handleScope(jsRuntime_);
458 napi_env env = jsRuntime_.GetNapiEnv();
459 napi_handle_scope scope = nullptr;
460 napi_open_handle_scope(env, &scope);
461 if (scope == nullptr) {
462 return ret;
463 }
464 napi_value napiUri = nullptr;
465 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
466 if (status != napi_ok) {
467 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
468 napi_close_handle_scope(env, scope);
469 return ret;
470 }
471 napi_value napiMimeTypeFilter = nullptr;
472 status = napi_create_string_utf8(env, mimeTypeFilter.c_str(), NAPI_AUTO_LENGTH, &napiMimeTypeFilter);
473 if (status != napi_ok) {
474 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
475 napi_close_handle_scope(env, scope);
476 return ret;
477 }
478 napi_value argv[] = {napiUri, napiMimeTypeFilter};
479 //represents this function has 2 parameters
480 CallObjectMethod("getFileTypes", argv, 2);
481 napi_close_handle_scope(env, scope);
482 return ret;
483 }
484
OpenFile(const Uri & uri,const std::string & mode)485 int JsDataShareExtAbility::OpenFile(const Uri &uri, const std::string &mode)
486 {
487 auto ret = DataShareExtAbility::OpenFile(uri, mode);
488 HandleScope handleScope(jsRuntime_);
489 napi_env env = jsRuntime_.GetNapiEnv();
490 napi_handle_scope scope = nullptr;
491 napi_open_handle_scope(env, &scope);
492 if (scope == nullptr) {
493 return ret;
494 }
495 napi_value napiUri = nullptr;
496 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
497 if (status != napi_ok) {
498 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
499 napi_close_handle_scope(env, scope);
500 return ret;
501 }
502 napi_value napiMode = nullptr;
503 status = napi_create_string_utf8(env, mode.c_str(), NAPI_AUTO_LENGTH, &napiMode);
504 if (status != napi_ok) {
505 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
506 napi_close_handle_scope(env, scope);
507 return ret;
508 }
509 napi_value argv[] = {napiUri, napiMode};
510 //represents this function has 2 parameters
511 CallObjectMethod("openFile", argv, 2);
512 napi_close_handle_scope(env, scope);
513 return ret;
514 }
515
OpenRawFile(const Uri & uri,const std::string & mode)516 int JsDataShareExtAbility::OpenRawFile(const Uri &uri, const std::string &mode)
517 {
518 auto ret = DataShareExtAbility::OpenRawFile(uri, mode);
519 HandleScope handleScope(jsRuntime_);
520 napi_env env = jsRuntime_.GetNapiEnv();
521 napi_handle_scope scope = nullptr;
522 napi_open_handle_scope(env, &scope);
523 if (scope == nullptr) {
524 return ret;
525 }
526 napi_value napiUri = nullptr;
527 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
528 if (status != napi_ok) {
529 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
530 napi_close_handle_scope(env, scope);
531 return ret;
532 }
533 napi_value napiMode = nullptr;
534 status = napi_create_string_utf8(env, mode.c_str(), NAPI_AUTO_LENGTH, &napiMode);
535 if (status != napi_ok) {
536 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
537 napi_close_handle_scope(env, scope);
538 return ret;
539 }
540 napi_value argv[] = {napiUri, napiMode};
541 //represents this function has 2 parameters
542 CallObjectMethod("openRawFile", argv, 2, false);
543 napi_close_handle_scope(env, scope);
544 return ret;
545 }
546
Insert(const Uri & uri,const DataShareValuesBucket & value)547 int JsDataShareExtAbility::Insert(const Uri &uri, const DataShareValuesBucket &value)
548 {
549 int ret = INVALID_VALUE;
550 ret = DataShareExtAbility::Insert(uri, value);
551 HandleScope handleScope(jsRuntime_);
552 napi_env env = jsRuntime_.GetNapiEnv();
553 napi_handle_scope scope = nullptr;
554 napi_open_handle_scope(env, &scope);
555 if (scope == nullptr) {
556 return ret;
557 }
558 napi_value napiUri = nullptr;
559 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
560 if (status != napi_ok) {
561 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
562 napi_close_handle_scope(env, scope);
563 return ret;
564 }
565 napi_value napiValue = NewInstance(env, const_cast<DataShareValuesBucket&>(value));
566 if (napiValue == nullptr) {
567 LOG_ERROR("failed to make new instance of rdbValueBucket.");
568 napi_close_handle_scope(env, scope);
569 return ret;
570 }
571 napi_value argv[] = {napiUri, napiValue};
572 //represents this function has 2 parameters
573 CallObjectMethod("insert", argv, 2);
574 napi_close_handle_scope(env, scope);
575 return ret;
576 }
577
Update(const Uri & uri,const DataSharePredicates & predicates,const DataShareValuesBucket & value)578 int JsDataShareExtAbility::Update(const Uri &uri, const DataSharePredicates &predicates,
579 const DataShareValuesBucket &value)
580 {
581 int ret = INVALID_VALUE;
582 ret = DataShareExtAbility::Update(uri, predicates, value);
583 HandleScope handleScope(jsRuntime_);
584 napi_env env = jsRuntime_.GetNapiEnv();
585 napi_handle_scope scope = nullptr;
586 napi_open_handle_scope(env, &scope);
587 if (scope == nullptr) {
588 return ret;
589 }
590 napi_value napiUri = nullptr;
591 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
592 if (status != napi_ok) {
593 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
594 napi_close_handle_scope(env, scope);
595 return ret;
596 }
597
598 napi_value napiPredicates = MakePredicates(env, predicates);
599 if (napiPredicates == nullptr) {
600 napi_close_handle_scope(env, scope);
601 return ret;
602 }
603
604 napi_value napiValue = NewInstance(env, const_cast<DataShareValuesBucket&>(value));
605 if (napiValue == nullptr) {
606 LOG_ERROR("failed to make new instance of rdbValueBucket.");
607 napi_close_handle_scope(env, scope);
608 return ret;
609 }
610
611 napi_value argv[] = {napiUri, napiPredicates, napiValue};
612 //represents this function has 3 parameters
613 CallObjectMethod("update", argv, 3);
614 napi_close_handle_scope(env, scope);
615 return ret;
616 }
617
BatchUpdate(const UpdateOperations & operations,std::vector<BatchUpdateResult> & results)618 int JsDataShareExtAbility::BatchUpdate(const UpdateOperations &operations,
619 std::vector<BatchUpdateResult> &results)
620 {
621 int ret = DataShareExtAbility::BatchUpdate(operations, results);
622 HandleScope handleScope(jsRuntime_);
623 napi_env env = jsRuntime_.GetNapiEnv();
624 napi_handle_scope scope = nullptr;
625 napi_open_handle_scope(env, &scope);
626 if (scope == nullptr) {
627 return ret;
628 }
629 napi_value jsMap = nullptr;
630 napi_status status = napi_create_object(env, &jsMap);
631 if (status != napi_ok) {
632 LOG_ERROR("napi_create_object : %{public}d", status);
633 napi_close_handle_scope(env, scope);
634 return ret;
635 }
636 for (const auto &valueArray : operations) {
637 napi_value napiValues = nullptr;
638 status = napi_create_array(env, &napiValues);
639 if (status != napi_ok) {
640 LOG_ERROR("napi_create_array status : %{public}d", status);
641 napi_close_handle_scope(env, scope);
642 return ret;
643 }
644 int32_t index = 0;
645 for (const auto &value : valueArray.second) {
646 napi_value jsUpdateOperation = MakeUpdateOperation(env, value);
647 if (jsUpdateOperation == nullptr) {
648 LOG_ERROR("MakeUpdateOperation failed");
649 napi_close_handle_scope(env, scope);
650 return ret;
651 }
652 napi_set_element(env, napiValues, index++, jsUpdateOperation);
653 }
654 napi_set_named_property(env, jsMap, valueArray.first.c_str(), napiValues);
655 }
656 napi_value argv[] = { jsMap };
657 CallObjectMethod("batchUpdate", argv, 1);
658 napi_close_handle_scope(env, scope);
659 return ret;
660 }
661
Delete(const Uri & uri,const DataSharePredicates & predicates)662 int JsDataShareExtAbility::Delete(const Uri &uri, const DataSharePredicates &predicates)
663 {
664 int ret = INVALID_VALUE;
665 ret = DataShareExtAbility::Delete(uri, predicates);
666 HandleScope handleScope(jsRuntime_);
667 napi_env env = jsRuntime_.GetNapiEnv();
668 napi_handle_scope scope = nullptr;
669 napi_open_handle_scope(env, &scope);
670 if (scope == nullptr) {
671 return ret;
672 }
673 napi_value napiUri = nullptr;
674 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
675 if (status != napi_ok) {
676 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
677 napi_close_handle_scope(env, scope);
678 return ret;
679 }
680
681 napi_value napiPredicates = MakePredicates(env, predicates);
682 if (napiPredicates == nullptr) {
683 napi_close_handle_scope(env, scope);
684 return ret;
685 }
686
687 napi_value argv[] = {napiUri, napiPredicates};
688 //represents this function has 2 parameters
689 CallObjectMethod("delete", argv, 2);
690 napi_close_handle_scope(env, scope);
691 return ret;
692 }
693
Query(const Uri & uri,const DataSharePredicates & predicates,std::vector<std::string> & columns,DatashareBusinessError & businessError)694 std::shared_ptr<DataShareResultSet> JsDataShareExtAbility::Query(const Uri &uri,
695 const DataSharePredicates &predicates, std::vector<std::string> &columns, DatashareBusinessError &businessError)
696 {
697 std::shared_ptr<DataShareResultSet> ret;
698 ret = DataShareExtAbility::Query(uri, predicates, columns, businessError);
699
700 HandleScope handleScope(jsRuntime_);
701 napi_env env = jsRuntime_.GetNapiEnv();
702 napi_handle_scope scope = nullptr;
703 napi_open_handle_scope(env, &scope);
704 if (scope == nullptr) {
705 return ret;
706 }
707 napi_value napiUri = nullptr;
708 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
709 if (status != napi_ok) {
710 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
711 napi_close_handle_scope(env, scope);
712 return ret;
713 }
714
715 napi_value napiPredicates = MakePredicates(env, predicates);
716 if (napiPredicates == nullptr) {
717 napi_close_handle_scope(env, scope);
718 return ret;
719 }
720
721 napi_value napiColumns = nullptr;
722 if (!MakeNapiColumn(env, napiColumns, columns)) {
723 LOG_ERROR("MakeNapiColumn failed");
724 napi_close_handle_scope(env, scope);
725 return ret;
726 }
727
728 napi_value argv[] = {napiUri, napiPredicates, napiColumns};
729 //represents this function has 3 parameters
730 CallObjectMethod("query", argv, 3);
731 napi_close_handle_scope(env, scope);
732 return ret;
733 }
734
GetType(const Uri & uri)735 std::string JsDataShareExtAbility::GetType(const Uri &uri)
736 {
737 auto ret = DataShareExtAbility::GetType(uri);
738 HandleScope handleScope(jsRuntime_);
739 napi_env env = jsRuntime_.GetNapiEnv();
740 napi_handle_scope scope = nullptr;
741 napi_open_handle_scope(env, &scope);
742 if (scope == nullptr) {
743 return ret;
744 }
745 napi_value napiUri = nullptr;
746 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
747 if (status != napi_ok) {
748 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
749 napi_close_handle_scope(env, scope);
750 return ret;
751 }
752 napi_value argv[] = {napiUri};
753 //represents this function has 1 parameter
754 CallObjectMethod("getType", argv, 1);
755 napi_close_handle_scope(env, scope);
756 return ret;
757 }
758
BatchInsert(const Uri & uri,const std::vector<DataShareValuesBucket> & values)759 int JsDataShareExtAbility::BatchInsert(const Uri &uri, const std::vector<DataShareValuesBucket> &values)
760 {
761 int ret = INVALID_VALUE;
762 ret = DataShareExtAbility::BatchInsert(uri, values);
763
764 HandleScope handleScope(jsRuntime_);
765 napi_env env = jsRuntime_.GetNapiEnv();
766 napi_handle_scope scope = nullptr;
767 napi_open_handle_scope(env, &scope);
768 if (scope == nullptr) {
769 return ret;
770 }
771 napi_value napiUri = nullptr;
772 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
773 if (status != napi_ok) {
774 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
775 napi_close_handle_scope(env, scope);
776 return ret;
777 }
778
779 napi_value napiValues = nullptr;
780 status = napi_create_array(env, &napiValues);
781 if (status != napi_ok) {
782 LOG_ERROR("napi_create_array status : %{public}d", status);
783 napi_close_handle_scope(env, scope);
784 return ret;
785 }
786 bool isArray = false;
787 if (napi_is_array(env, napiValues, &isArray) != napi_ok || !isArray) {
788 LOG_ERROR("JsDataShareExtAbility create array failed");
789 napi_close_handle_scope(env, scope);
790 return ret;
791 }
792 int32_t index = 0;
793 for (const auto &value : values) {
794 napi_value result = NewInstance(env, const_cast<DataShareValuesBucket&>(value));
795 if (result == nullptr) {
796 LOG_ERROR("failed to make new instance of rdbValueBucket.");
797 napi_close_handle_scope(env, scope);
798 return ret;
799 }
800 napi_set_element(env, napiValues, index++, result);
801 }
802 napi_value argv[] = {napiUri, napiValues};
803 //represents this function has 2 parameters
804 CallObjectMethod("batchInsert", argv, 2);
805 napi_close_handle_scope(env, scope);
806 return ret;
807 }
808
RegisterObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)809 bool JsDataShareExtAbility::RegisterObserver(const Uri &uri, const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
810 {
811 DataShareExtAbility::RegisterObserver(uri, dataObserver);
812 auto obsMgrClient = DataObsMgrClient::GetInstance();
813 if (obsMgrClient == nullptr) {
814 LOG_ERROR("obsMgrClient is nullptr");
815 return false;
816 }
817
818 ErrCode ret = obsMgrClient->RegisterObserver(uri, dataObserver);
819 if (ret != ERR_OK) {
820 LOG_ERROR("obsMgrClient->RegisterObserver error return %{public}d", ret);
821 return false;
822 }
823 return true;
824 }
825
UnregisterObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)826 bool JsDataShareExtAbility::UnregisterObserver(const Uri &uri, const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
827 {
828 DataShareExtAbility::UnregisterObserver(uri, dataObserver);
829 auto obsMgrClient = DataObsMgrClient::GetInstance();
830 if (obsMgrClient == nullptr) {
831 LOG_ERROR("obsMgrClient is nullptr");
832 return false;
833 }
834
835 ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver);
836 if (ret != ERR_OK) {
837 LOG_ERROR("obsMgrClient->UnregisterObserver error return %{public}d", ret);
838 return false;
839 }
840 return true;
841 }
842
NotifyChange(const Uri & uri)843 bool JsDataShareExtAbility::NotifyChange(const Uri &uri)
844 {
845 DataShareExtAbility::NotifyChange(uri);
846 auto obsMgrClient = DataObsMgrClient::GetInstance();
847 if (obsMgrClient == nullptr) {
848 LOG_ERROR("obsMgrClient is nullptr");
849 return false;
850 }
851
852 ErrCode ret = obsMgrClient->NotifyChange(uri);
853 if (ret != ERR_OK) {
854 LOG_ERROR("obsMgrClient->NotifyChange error return %{public}d", ret);
855 return false;
856 }
857 return true;
858 }
859
NormalizeUri(const Uri & uri)860 Uri JsDataShareExtAbility::NormalizeUri(const Uri &uri)
861 {
862 auto ret = DataShareExtAbility::NormalizeUri(uri);
863 HandleScope handleScope(jsRuntime_);
864 napi_env env = jsRuntime_.GetNapiEnv();
865 napi_handle_scope scope = nullptr;
866 napi_open_handle_scope(env, &scope);
867 if (scope == nullptr) {
868 return ret;
869 }
870 napi_value napiUri = nullptr;
871 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
872 if (status != napi_ok) {
873 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
874 napi_close_handle_scope(env, scope);
875 return ret;
876 }
877 napi_value argv[] = {napiUri};
878 //represents this function has 1 parameter
879 CallObjectMethod("normalizeUri", argv, 1);
880 napi_close_handle_scope(env, scope);
881 return ret;
882 }
883
DenormalizeUri(const Uri & uri)884 Uri JsDataShareExtAbility::DenormalizeUri(const Uri &uri)
885 {
886 auto ret = DataShareExtAbility::DenormalizeUri(uri);
887 HandleScope handleScope(jsRuntime_);
888 napi_env env = jsRuntime_.GetNapiEnv();
889 napi_handle_scope scope = nullptr;
890 napi_open_handle_scope(env, &scope);
891 if (scope == nullptr) {
892 return ret;
893 }
894 napi_value napiUri = nullptr;
895 napi_status status = napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri);
896 if (status != napi_ok) {
897 LOG_ERROR("napi_create_string_utf8 status : %{public}d", status);
898 napi_close_handle_scope(env, scope);
899 return ret;
900 }
901 napi_value argv[] = {napiUri};
902 //represents this function has 1 parameter
903 CallObjectMethod("denormalizeUri", argv, 1);
904 napi_close_handle_scope(env, scope);
905 return ret;
906 }
907
MakePredicates(napi_env env,const DataSharePredicates & predicates)908 napi_value JsDataShareExtAbility::MakePredicates(napi_env env, const DataSharePredicates &predicates)
909 {
910 std::shared_ptr<DataSharePredicates> predicatesPtr = std::make_shared<DataSharePredicates>(predicates);
911 if (predicatesPtr == nullptr) {
912 LOG_ERROR("No memory allocated for predicates");
913 return nullptr;
914 }
915 napi_value napiPredicates = DataSharePredicatesProxy::NewInstance(env, predicatesPtr);
916 if (napiPredicates == nullptr) {
917 LOG_ERROR("failed to make new instance of DataSharePredicates.");
918 }
919 return napiPredicates;
920 }
921
UnWrapBusinessError(napi_env env,napi_value info,DatashareBusinessError & businessError)922 void JsDataShareExtAbility::UnWrapBusinessError(napi_env env, napi_value info,
923 DatashareBusinessError& businessError)
924 {
925 std::string code = UnWrapProperty(env, info, "code");
926 businessError.SetCode(code);
927 std::string message = UnWrapProperty(env, info, "message");
928 businessError.SetMessage(message);
929 }
930
UnWrapProperty(napi_env env,napi_value info,const std::string & key)931 std::string JsDataShareExtAbility::UnWrapProperty(napi_env env, napi_value info, const std::string &key)
932 {
933 napi_valuetype type = UnWrapPropertyType(env, info, key);
934 if (type == napi_valuetype::napi_number) {
935 int value;
936 UnwrapInt32ByPropertyName(env, info, key.c_str(), value);
937 return std::to_string(value);
938 } else if (type == napi_valuetype::napi_string) {
939 std::string value;
940 UnwrapStringByPropertyName(env, info, key.c_str(), value);
941 return value;
942 } else {
943 LOG_ERROR("ValueType should be napi_number or napi_string, property is %{public}s", key.c_str());
944 return "";
945 }
946 }
947
UnWrapPropertyType(napi_env env,napi_value info,const std::string & propertyKey)948 napi_valuetype JsDataShareExtAbility::UnWrapPropertyType(napi_env env, napi_value info,
949 const std::string &propertyKey)
950 {
951 napi_value key = nullptr;
952 napi_status status = napi_create_string_utf8(env, propertyKey.c_str(), propertyKey.size(), &key);
953 if (status != napi_ok) {
954 LOG_ERROR("napi_create_string_utf8 failed, status is %{public}d, propertyKey is %{public}s",
955 status, propertyKey.c_str());
956 return napi_undefined;
957 }
958
959 bool result = false;
960 napi_has_property(env, info, key, &result);
961 if (!result) {
962 LOG_WARN("not contains property is %{public}s", propertyKey.c_str());
963 return napi_undefined;
964 }
965
966 napi_value value = nullptr;
967 status = napi_get_property(env, info, key, &value);
968 if (status != napi_ok) {
969 LOG_ERROR("failed to napi_get_property, status is %{public}d, propertyKey is %{public}s",
970 status, propertyKey.c_str());
971 return napi_undefined;
972 }
973
974 napi_valuetype type = napi_undefined;
975 napi_typeof(env, value, &type);
976 return type;
977 }
978
NotifyToDataShareService()979 void JsDataShareExtAbility::NotifyToDataShareService()
980 {
981 auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
982 if (manager == nullptr) {
983 LOG_ERROR("get system ability manager failed");
984 return;
985 }
986 auto remoteObject = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID);
987 if (remoteObject == nullptr) {
988 LOG_ERROR("CheckSystemAbility failed");
989 return;
990 }
991 auto serviceProxy = std::make_shared<DataShareKvServiceProxy>(remoteObject);
992 if (serviceProxy == nullptr) {
993 LOG_ERROR("make_shared failed");
994 return;
995 }
996 auto remote = serviceProxy->GetFeatureInterface("data_share");
997 if (remote == nullptr) {
998 LOG_ERROR("Get DataShare service failed!");
999 return;
1000 }
1001 MessageParcel data;
1002 MessageParcel reply;
1003 MessageOption option(MessageOption::TF_ASYNC);
1004 if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) {
1005 LOG_ERROR("Write descriptor failed!");
1006 return;
1007 }
1008 remote->SendRequest(
1009 static_cast<uint32_t>(DataShareServiceInterfaceCode::DATA_SHARE_SERVICE_CMD_NOTIFY), data, reply, option);
1010 }
1011
MakeUpdateOperation(napi_env env,const UpdateOperation & updateOperation)1012 napi_value JsDataShareExtAbility::MakeUpdateOperation(napi_env env, const UpdateOperation &updateOperation)
1013 {
1014 napi_value jsValueBucket = NewInstance(env, const_cast<DataShareValuesBucket&>(updateOperation.valuesBucket));
1015 napi_value jsPredicates = MakePredicates(env, updateOperation.predicates);
1016 if (jsValueBucket == nullptr || jsPredicates == nullptr) {
1017 LOG_ERROR("failed to make new instance of UpdateOperation.");
1018 return nullptr;
1019 }
1020 napi_value jsUpdateOperation = nullptr;
1021 napi_status status = napi_create_object(env, &jsUpdateOperation);
1022 if (status != napi_ok) {
1023 LOG_ERROR("JsDataShareExtAbility create object failed");
1024 return nullptr;
1025 }
1026 std::string valuesKey = "values";
1027 std::string presKey = "predicates";
1028 napi_value jsValueKey = DataShareJSUtils::Convert2JSValue(env, valuesKey);
1029 napi_value jsPresKey = DataShareJSUtils::Convert2JSValue(env, presKey);
1030 napi_set_property(env, jsUpdateOperation, jsValueKey, jsValueBucket);
1031 napi_set_property(env, jsUpdateOperation, jsPresKey, jsPredicates);
1032 return jsUpdateOperation;
1033 }
1034
MakeNapiColumn(napi_env env,napi_value & napiColumns,const std::vector<std::string> & columns)1035 bool MakeNapiColumn(napi_env env, napi_value &napiColumns, const std::vector<std::string> &columns)
1036 {
1037 napi_status status = napi_create_array(env, &napiColumns);
1038 if (status != napi_ok) {
1039 LOG_ERROR("napi_create_array status : %{public}d", status);
1040 return false;
1041 }
1042
1043 bool isArray = false;
1044 if (napi_is_array(env, napiColumns, &isArray) != napi_ok || !isArray) {
1045 LOG_ERROR("JsDataShareExtAbility create array failed");
1046 return false;
1047 }
1048
1049 int32_t index = 0;
1050 for (const auto &column : columns) {
1051 napi_value result = nullptr;
1052 napi_create_string_utf8(env, column.c_str(), column.length(), &result);
1053 napi_set_element(env, napiColumns, index++, result);
1054 }
1055
1056 return true;
1057 }
1058 } // namespace DataShare
1059 } // namespace OHOS