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