• 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 #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