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