• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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