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