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