1 /*
2 * Copyright (c) 2022-2023 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_form_provider.h"
17
18 #include <cinttypes>
19 #include <vector>
20
21 #include "fms_log_wrapper.h"
22 #include "form_constants.h"
23 #include "form_mgr_errors.h"
24 #include "form_mgr.h"
25 #include "running_form_info.h"
26 #include "js_runtime_utils.h"
27 #include "ipc_skeleton.h"
28 #include "napi_common_util.h"
29 #include "napi_common_want.h"
30 #include "napi_form_util.h"
31 #include "napi/native_api.h"
32 #include "napi/native_node_api.h"
33 #include "runtime.h"
34 #include "tokenid_kit.h"
35
36 namespace OHOS {
37 namespace AbilityRuntime {
38 using namespace OHOS;
39 using namespace OHOS::AAFwk;
40 using namespace OHOS::AppExecFwk;
41 namespace {
42 constexpr size_t ARGS_SIZE_ZERO = 0;
43 constexpr size_t ARGS_SIZE_ONE = 1;
44 constexpr size_t ARGS_SIZE_TWO = 2;
45 constexpr size_t ARGS_SIZE_THREE = 3;
46 const std::string IS_FORM_AGENT = "isFormAgent";
47
CheckParamNum(napi_env env,size_t argc,size_t minParamNum,size_t maxParamNum)48 bool CheckParamNum(napi_env env, size_t argc, size_t minParamNum, size_t maxParamNum)
49 {
50 HILOG_DEBUG("argc is %{public}zu,param range is [%{public}zu,%{public}zu]",
51 argc, minParamNum, maxParamNum);
52 if (argc > maxParamNum || argc < minParamNum) {
53 HILOG_ERROR("invalid param number %{public}zu", argc);
54 std::string errMsg = "[" + std::to_string(minParamNum) + ", " + std::to_string(maxParamNum) + "]";
55 NapiFormUtil::ThrowParamNumError(env, std::to_string(argc), errMsg);
56 return false;
57 }
58 return true;
59 }
60
ConvertFormInfoFilterThrow(napi_env env,napi_value jsValue,AppExecFwk::FormInfoFilter & formInfoFilter)61 static bool ConvertFormInfoFilterThrow(napi_env env, napi_value jsValue, AppExecFwk::FormInfoFilter &formInfoFilter)
62 {
63 napi_valuetype jsValueType = napi_undefined;
64 napi_typeof(env, jsValue, &jsValueType);
65 if (jsValueType != napi_object) {
66 HILOG_ERROR("an object is expected, but an argument of different type is passed in");
67 NapiFormUtil::ThrowParamTypeError(env, "filter", "formInfo.FormInfoFilter");
68 return false;
69 }
70
71 napi_value nativeDataValue = nullptr;
72 napi_status ret = napi_get_named_property(env, jsValue, "moduleName", &nativeDataValue);
73 if (ret != napi_ok) {
74 HILOG_ERROR("get property failed");
75 NapiFormUtil::ThrowParamError(env, "Failed to get property.");
76 return false;
77 }
78 napi_valuetype nativeDataValueType = napi_undefined;
79 napi_typeof(env, nativeDataValue, &nativeDataValueType);
80 if (nativeDataValue == nullptr || (nativeDataValueType != napi_undefined &&
81 !ConvertFromJsValue(env, nativeDataValue, formInfoFilter.moduleName))) {
82 HILOG_ERROR("convert nativeDataValue failed");
83 NapiFormUtil::ThrowParamError(env, "Failed to convert FormInfoFilter.");
84 return false;
85 }
86
87 HILOG_INFO("module:%{public}s", formInfoFilter.moduleName.c_str());
88
89 return true;
90 }
91
ConvertFormId(napi_env env,napi_value jsValue,int64_t & formId)92 static bool ConvertFormId(napi_env env, napi_value jsValue, int64_t &formId)
93 {
94 std::string strFormId;
95 if (!ConvertFromJsValue(env, jsValue, strFormId)) {
96 HILOG_ERROR("convert strFormId failed");
97 return false;
98 }
99
100 if (strFormId.empty()) {
101 HILOG_ERROR("empty strFormId");
102 }
103
104 if (!ConvertStringToInt64(strFormId, formId)) {
105 HILOG_ERROR("convert string formId to int64 failed");
106 return false;
107 }
108 return true;
109 }
110 }
111
GetStringByProp(napi_env env,napi_value value,const std::string & prop)112 static std::string GetStringByProp(napi_env env, napi_value value, const std::string &prop)
113 {
114 HILOG_DEBUG("GetStringByProp start");
115 std::string result;
116 bool propExist = false;
117 napi_value propValue = nullptr;
118 napi_valuetype valueType = napi_undefined;
119 napi_has_named_property(env, value, prop.c_str(), &propExist);
120 if (!propExist) {
121 HILOG_ERROR("prop[%{public}s] absent", prop.c_str());
122 return result;
123 }
124 napi_get_named_property(env, value, prop.c_str(), &propValue);
125 if (propValue == nullptr) {
126 HILOG_ERROR("prop[%{public}s] get error", prop.c_str());
127 return result;
128 }
129 napi_typeof(env, propValue, &valueType);
130 if (valueType != napi_string) {
131 HILOG_ERROR("prop[%{public}s] not string", prop.c_str());
132 return result;
133 }
134 size_t size = 0;
135 if (napi_get_value_string_utf8(env, propValue, nullptr, 0, &size) != napi_ok) {
136 HILOG_ERROR("prop[%{public}s] get size error", prop.c_str());
137 return result;
138 }
139 result.reserve(size + 1);
140 result.resize(size);
141 if (napi_get_value_string_utf8(env, propValue, result.data(), (size + 1), &size) != napi_ok) {
142 HILOG_ERROR("prop[%{public}s] get value error", prop.c_str());
143 return "";
144 }
145 return result;
146 }
147
Finalizer(napi_env env,void * data,void * hint)148 void JsFormProvider::Finalizer(napi_env env, void *data, void *hint)
149 {
150 HILOG_INFO("call");
151 std::unique_ptr<JsFormProvider>(static_cast<JsFormProvider *>(data));
152 }
153
GetFormsInfo(napi_env env,napi_callback_info info)154 napi_value JsFormProvider::GetFormsInfo(napi_env env, napi_callback_info info)
155 {
156 GET_CB_INFO_AND_CALL(env, info, JsFormProvider, OnGetFormsInfo);
157 }
158
OnGetFormsInfoParseParam(NapiParamPackage & napiParam,size_t & convertArgc,bool & isPromise,AppExecFwk::FormInfoFilter & formInfoFilter)159 bool JsFormProvider::OnGetFormsInfoParseParam(NapiParamPackage &napiParam,
160 size_t &convertArgc, bool &isPromise, AppExecFwk::FormInfoFilter &formInfoFilter)
161 {
162 napi_env env = napiParam.env;
163 size_t argc = napiParam.argc;
164 napi_value* argv = napiParam.argv;
165 // GetformsInfo()
166 if (argc == ARGS_SIZE_ZERO) {
167 isPromise = true;
168 }
169 if (argc == ARGS_SIZE_ONE) {
170 napi_valuetype argvZeroType = napi_undefined;
171 napi_typeof(env, argv[PARAM0], &argvZeroType);
172 if (argvZeroType != napi_undefined) {
173 // GetformsInfo(*)
174 if (argvZeroType == napi_function) {
175 // GetformsInfo(callback)
176 isPromise = false;
177 } else {
178 // GetformsInfo(*);GetformsInfo(fliter)
179 if (ConvertFormInfoFilterThrow(env, argv[PARAM0], formInfoFilter)) {
180 convertArgc++;
181 isPromise = true;
182 } else {
183 // no default value
184 return false;
185 }
186 }
187 } else {
188 isPromise = true;
189 }
190 }
191
192 if (argc >= ARGS_SIZE_TWO) {
193 napi_valuetype argvType = napi_undefined;
194 napi_typeof(env, argv[PARAM0], &argvType);
195 if (argvType != napi_undefined) {
196 if (argvType == napi_function) {
197 // GetformsInfo(callback, *)
198 isPromise = false;
199 } else {
200 // GetformsInfo(fliter, *) || GetformsInfo(fliter, callback)
201 if (ConvertFormInfoFilterThrow(env, argv[PARAM0], formInfoFilter)) {
202 convertArgc++;
203 // GetformsInfo(fliter, callback)
204 napi_valuetype paramTwoType = napi_undefined;
205 napi_typeof(env, argv[PARAM1], ¶mTwoType);
206 isPromise = paramTwoType != napi_function;
207 } else {
208 HILOG_ERROR("convert form info filter failed");
209 return false;
210 }
211 }
212 } else {
213 isPromise = true;
214 }
215 }
216 return true;
217 }
218
OnGetFormsInfo(napi_env env,size_t argc,napi_value * argv)219 napi_value JsFormProvider::OnGetFormsInfo(napi_env env, size_t argc, napi_value* argv)
220 {
221 HILOG_DEBUG("call");
222
223 size_t convertArgc = 0;
224 bool isPromise = false;
225 FormInfoFilter formInfoFilter;
226
227 NapiParamPackage napiParam(env, argc, argv);
228
229 if (!OnGetFormsInfoParseParam(napiParam, convertArgc, isPromise, formInfoFilter)) {
230 HILOG_ERROR("parse param failed");
231 return CreateJsUndefined(env);
232 }
233
234 NapiAsyncTask::CompleteCallback complete =
235 [formInfoFilter](napi_env env, NapiAsyncTask &task, int32_t status) {
236 std::vector<FormInfo> formInfos;
237 auto ret = FormMgr::GetInstance().GetFormsInfo(formInfoFilter, formInfos);
238 if (ret != ERR_OK) {
239 task.Reject(env, NapiFormUtil::CreateErrorByInternalErrorCode(env, ret));
240 return;
241 }
242 task.ResolveWithNoError(env, CreateFormInfos(env, formInfos));
243 };
244
245 napi_value lastParam = isPromise ? nullptr : argv[convertArgc];
246 napi_value result = nullptr;
247 NapiAsyncTask::ScheduleWithDefaultQos("JsFormProvider::OnGetFormsInfo",
248 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
249 return result;
250 }
251
GetPublishedFormInfoById(napi_env env,napi_callback_info info)252 napi_value JsFormProvider::GetPublishedFormInfoById(napi_env env, napi_callback_info info)
253 {
254 GET_CB_INFO_AND_CALL(env, info, JsFormProvider, OnGetPublishedFormInfoById);
255 }
256
OnGetPublishedFormInfoById(napi_env env,size_t argc,napi_value * argv)257 napi_value JsFormProvider::OnGetPublishedFormInfoById(napi_env env, size_t argc, napi_value* argv)
258 {
259 HILOG_DEBUG("call");
260 if (CheckParamNum(env, argc, ARGS_SIZE_ONE, ARGS_SIZE_TWO) == false) {
261 return CreateJsUndefined(env);
262 }
263 napi_valuetype paramZeroType = napi_undefined;
264 napi_typeof(env, argv[PARAM0], ¶mZeroType);
265 if (paramZeroType != napi_string) {
266 NapiFormUtil::ThrowParamTypeError(env, "formId", "string");
267 return CreateJsUndefined(env);
268 }
269 int64_t formId = 0;
270 std::string strFormId;
271 if (!ConvertFromJsValue(env, argv[PARAM0], strFormId)) {
272 HILOG_ERROR("ConvertFromJsValue failed");
273 NapiFormUtil::ThrowParamTypeError(env, "formId", "string");
274 return CreateJsUndefined(env);
275 }
276 if (!ConvertStringToInt64(strFormId, formId)) {
277 HILOG_ERROR("convert form string failed");
278 NapiFormUtil::ThrowParamError(env, "Failed to convert formId.");
279 return CreateJsUndefined(env);
280 }
281
282 HILOG_INFO("before GetPublishedFormInfoById, formId:%{public}" PRId64, formId);
283 NapiAsyncTask::CompleteCallback complete =
284 [formId](napi_env env, NapiAsyncTask &task, int32_t status) {
285 RunningFormInfo formInfo;
286 auto ret = FormMgr::GetInstance().GetPublishedFormInfoById(formId, formInfo);
287 if (ret != ERR_OK) {
288 task.Reject(env, NapiFormUtil::CreateErrorByInternalErrorCode(env, ret));
289 return;
290 }
291 task.ResolveWithNoError(env, CreateRunningFormInfo(env, formInfo));
292 };
293
294 napi_value lastParam = (argc == ARGS_SIZE_TWO) ? argv[PARAM1] : nullptr;
295 napi_value result = nullptr;
296 NapiAsyncTask::ScheduleWithDefaultQos("JsFormProvider::OnGetPublishedFormInfoById",
297 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
298 return result;
299 }
300
GetPublishedFormInfos(napi_env env,napi_callback_info info)301 napi_value JsFormProvider::GetPublishedFormInfos(napi_env env, napi_callback_info info)
302 {
303 GET_CB_INFO_AND_CALL(env, info, JsFormProvider, OnGetPublishedFormInfos);
304 }
305
OnGetPublishedFormInfos(napi_env env,size_t argc,napi_value * argv)306 napi_value JsFormProvider::OnGetPublishedFormInfos(napi_env env, size_t argc, napi_value* argv)
307 {
308 HILOG_DEBUG("call");
309
310 NapiAsyncTask::CompleteCallback complete =
311 [](napi_env env, NapiAsyncTask &task, int32_t status) {
312 std::vector<RunningFormInfo> formInfos;
313 auto ret = FormMgr::GetInstance().GetPublishedFormInfos(formInfos);
314 if (ret != ERR_OK) {
315 task.Reject(env, NapiFormUtil::CreateErrorByInternalErrorCode(env, ret));
316 return;
317 }
318 task.ResolveWithNoError(env, CreateRunningFormInfos(env, formInfos));
319 };
320
321 napi_value result = nullptr;
322 NapiAsyncTask::ScheduleWithDefaultQos("JsFormProvider::OnGetPublishedFormInfos",
323 env, CreateAsyncTaskWithLastParam(env, nullptr, nullptr, std::move(complete), &result));
324 return result;
325 }
OpenFormManager(napi_env env,napi_callback_info info)326 napi_value JsFormProvider::OpenFormManager(napi_env env, napi_callback_info info)
327 {
328 GET_CB_INFO_AND_CALL(env, info, JsFormProvider, OnOpenFormManager);
329 }
330
OnOpenFormManager(napi_env env,size_t argc,napi_value * argv)331 napi_value JsFormProvider::OnOpenFormManager(napi_env env, size_t argc, napi_value* argv)
332 {
333 HILOG_DEBUG("call");
334 Want want;
335 if (!AppExecFwk::UnwrapWant(env, argv[PARAM0], want)) {
336 HILOG_ERROR("fail convert want");
337 NapiFormUtil::ThrowParamError(env, "Failed to convert want.");
338 return CreateJsUndefined(env);
339 }
340
341 const std::string bundleName = want.GetBundle();
342 const std::string abilityName = want.GetElement().GetAbilityName();
343 want.SetElementName(bundleName, abilityName);
344 want.SetAction(AppExecFwk::Constants::FORM_PAGE_ACTION);
345 want.SetParam(AppExecFwk::Constants::PARAM_PAGE_ROUTER_SERVICE_CODE,
346 AppExecFwk::Constants::PAGE_ROUTER_SERVICE_CODE_FORM_MANAGE);
347 const std::string key = AppExecFwk::Constants::PARMA_REQUEST_METHOD;
348 const std::string value = AppExecFwk::Constants::OPEN_FORM_MANAGE_VIEW;
349 want.SetParam(key, value);
350 HILOG_DEBUG("JsFormProvider OnOpenFormManager want:%{public}s", want.ToString().c_str());
351
352 NapiAsyncTask::CompleteCallback complete =
353 [want](napi_env env, NapiAsyncTask &task, int32_t status) {
354 auto ret = FormMgr::GetInstance().StartAbilityByFms(want);
355 if (ret != ERR_OK) {
356 task.Reject(env, NapiFormUtil::CreateErrorByInternalErrorCode(env, ret));
357 return;
358 }
359 task.ResolveWithNoError(env, CreateJsUndefined(env));
360 };
361
362 napi_value result = nullptr;
363 NapiAsyncTask::ScheduleWithDefaultQos("JsFormProvider::OnOpenFormManager",
364 env, CreateAsyncTaskWithLastParam(env, nullptr, nullptr, std::move(complete), &result));
365 return result;
366 }
367
SetFormNextRefreshTime(napi_env env,napi_callback_info info)368 napi_value JsFormProvider::SetFormNextRefreshTime(napi_env env, napi_callback_info info)
369 {
370 GET_CB_INFO_AND_CALL(env, info, JsFormProvider, OnSetFormNextRefreshTime);
371 }
372
OnSetFormNextRefreshTime(napi_env env,size_t argc,napi_value * argv)373 napi_value JsFormProvider::OnSetFormNextRefreshTime(napi_env env, size_t argc, napi_value* argv)
374 {
375 HILOG_DEBUG("call");
376 if (CheckParamNum(env, argc, ARGS_SIZE_TWO, ARGS_SIZE_THREE) == false) {
377 return CreateJsUndefined(env);
378 }
379 napi_valuetype paramZeroType = napi_undefined;
380 napi_typeof(env, argv[PARAM0], ¶mZeroType);
381 if (paramZeroType != napi_string) {
382 NapiFormUtil::ThrowParamTypeError(env, "formId", "string");
383 return CreateJsUndefined(env);
384 }
385 int64_t formId = 0;
386 std::string strFormId;
387 if (!ConvertFromJsValue(env, argv[PARAM0], strFormId)) {
388 HILOG_ERROR("ConvertFromJsValue failed");
389 NapiFormUtil::ThrowParamTypeError(env, "formId", "string");
390 return CreateJsUndefined(env);
391 }
392 if (!ConvertStringToInt64(strFormId, formId)) {
393 HILOG_ERROR("convert form string failed");
394 NapiFormUtil::ThrowParamError(env, "Failed to convert formId.");
395 return CreateJsUndefined(env);
396 }
397 napi_valuetype paramOneType = napi_undefined;
398 napi_typeof(env, argv[PARAM1], ¶mOneType);
399 if (paramOneType != napi_number) {
400 NapiFormUtil::ThrowParamTypeError(env, "minute", "number");
401 return CreateJsUndefined(env);
402 }
403 int32_t time;
404 if (!ConvertFromJsValue(env, argv[PARAM1], time)) {
405 NapiFormUtil::ThrowParamTypeError(env, "minute", "number");
406 return CreateJsUndefined(env);
407 }
408 NapiAsyncTask::CompleteCallback complete = [formId, time](napi_env env, NapiAsyncTask &task, int32_t status) {
409 int32_t ret = FormMgr::GetInstance().SetNextRefreshTime(formId, time);
410 if (ret != ERR_OK) {
411 task.Reject(env, NapiFormUtil::CreateErrorByInternalErrorCode(env, ret));
412 return;
413 }
414 task.ResolveWithNoError(env, CreateJsUndefined(env));
415 };
416 napi_value lastParam = (argc == ARGS_SIZE_THREE) ? argv[PARAM2] : nullptr;
417 napi_value result = nullptr;
418 NapiAsyncTask::ScheduleWithDefaultQos("JsFormProvider::OnSetFormNextRefreshTime",
419 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
420 return result;
421 }
422
UpdateForm(napi_env env,napi_callback_info info)423 napi_value JsFormProvider::UpdateForm(napi_env env, napi_callback_info info)
424 {
425 GET_CB_INFO_AND_CALL(env, info, JsFormProvider, OnUpdateForm);
426 }
427
OnUpdateFormParseParam(napi_env env,size_t argc,napi_value * argv,int64_t & formId)428 napi_value JsFormProvider::OnUpdateFormParseParam(napi_env env, size_t argc, napi_value* argv, int64_t &formId)
429 {
430 if (CheckParamNum(env, argc, ARGS_SIZE_TWO, ARGS_SIZE_THREE) == false) {
431 return CreateJsUndefined(env);
432 }
433 if (!ConvertFormId(env, argv[PARAM0], formId)) {
434 HILOG_ERROR("convert form string failed");
435 NapiFormUtil::ThrowParamError(env, "Failed to convert formId.");
436 return CreateJsUndefined(env);
437 }
438 napi_valuetype paramOneType = napi_undefined;
439 napi_typeof(env, argv[PARAM1], ¶mOneType);
440 if (paramOneType != napi_object) {
441 HILOG_ERROR("formBindingData not napi_object");
442 NapiFormUtil::ThrowParamTypeError(env, "formBindingData", "formBindingData.FormBindingData");
443 return CreateJsUndefined(env);
444 }
445 return nullptr;
446 }
447
OnUpdateForm(napi_env env,size_t argc,napi_value * argv)448 napi_value JsFormProvider::OnUpdateForm(napi_env env, size_t argc, napi_value* argv)
449 {
450 HILOG_DEBUG("call");
451
452 int64_t formId = 0;
453 napi_value parseResult = OnUpdateFormParseParam(env, argc, argv, formId);
454 if (parseResult != nullptr) {
455 HILOG_ERROR("parse param failed");
456 return parseResult;
457 }
458
459 auto formProviderData = std::make_shared<OHOS::AppExecFwk::FormProviderData>();
460 std::string formDataStr = GetStringByProp(env, argv[PARAM1], "data");
461 formProviderData->SetDataString(formDataStr);
462 formProviderData->ParseImagesData();
463
464 std::vector<AppExecFwk::FormDataProxy> formDataProxies;
465 napi_value nativeProxies = nullptr;
466 napi_get_named_property(env, argv[PARAM1], "proxies", &nativeProxies);
467 if (nativeProxies != nullptr) {
468 ConvertFromDataProxies(env, nativeProxies, formDataProxies);
469 }
470
471 NapiAsyncTask::CompleteCallback complete =
472 [formId, data = formProviderData, formDataProxies](napi_env env, NapiAsyncTask &task, int32_t status) {
473 int32_t ret = FormMgr::GetInstance().UpdateForm(formId, *data, formDataProxies);
474 if (ret != ERR_OK) {
475 task.Reject(env, NapiFormUtil::CreateErrorByInternalErrorCode(env, ret));
476 return;
477 }
478 task.ResolveWithNoError(env, CreateJsUndefined(env));
479 };
480 napi_value lastParam = (argc == ARGS_SIZE_THREE) ? argv[PARAM2] : nullptr;
481 napi_value result = nullptr;
482 NapiAsyncTask::ScheduleWithDefaultQos("JsFormProvider::OnUpdateForm",
483 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
484 return result;
485 }
486
IsRequestPublishFormSupported(napi_env env,napi_callback_info info)487 napi_value JsFormProvider::IsRequestPublishFormSupported(napi_env env, napi_callback_info info)
488 {
489 GET_CB_INFO_AND_CALL(env, info, JsFormProvider, OnIsRequestPublishFormSupported);
490 }
491
OnIsRequestPublishFormSupported(napi_env env,size_t argc,napi_value * argv)492 napi_value JsFormProvider::OnIsRequestPublishFormSupported(napi_env env, size_t argc, napi_value* argv)
493 {
494 HILOG_DEBUG("call");
495 if (CheckParamNum(env, argc, ARGS_SIZE_ZERO, ARGS_SIZE_ONE) == false) {
496 return CreateJsUndefined(env);
497 }
498
499 auto selfToken = IPCSkeleton::GetSelfTokenID();
500 if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) {
501 HILOG_ERROR("The application not system-app,can't use system-api");
502 NapiFormUtil::ThrowByExternalErrorCode(env, ERR_FORM_EXTERNAL_NOT_SYSTEM_APP);
503 return CreateJsUndefined(env);
504 }
505
506 NapiAsyncTask::CompleteCallback complete = [](napi_env env, NapiAsyncTask &task, int32_t status) {
507 bool value = FormMgr::GetInstance().IsRequestPublishFormSupported();
508 napi_value jsValue = nullptr;
509 napi_get_boolean(env, value, &jsValue);
510 task.ResolveWithNoError(env, jsValue);
511 };
512 napi_value lastParam = (argc == ARGS_SIZE_ONE) ? argv[PARAM0] : nullptr;
513 napi_value result = nullptr;
514 NapiAsyncTask::ScheduleWithDefaultQos("JsFormProvider::OnIsRequestPublishFormSupported",
515 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
516 return result;
517 }
518
RequestPublishForm(napi_env env,napi_callback_info info)519 napi_value JsFormProvider::RequestPublishForm(napi_env env, napi_callback_info info)
520 {
521 GET_CB_INFO_AND_CALL(env, info, JsFormProvider, OnRequestPublishForm);
522 }
523
OnRequestPublishForm(napi_env env,size_t argc,napi_value * argv)524 napi_value JsFormProvider::OnRequestPublishForm(napi_env env, size_t argc, napi_value* argv)
525 {
526 HILOG_DEBUG("call");
527 if (CheckParamNum(env, argc, ARGS_SIZE_ONE, ARGS_SIZE_THREE) == false) {
528 return CreateJsUndefined(env);
529 }
530
531 auto asyncCallbackInfo = std::make_shared<RequestPublishFormCallbackInfo>();
532 decltype(argc) convertArgc = 0;
533 napi_valuetype paramZeroType = napi_undefined;
534 napi_typeof(env, argv[PARAM0], ¶mZeroType);
535 if (paramZeroType != napi_object) {
536 HILOG_ERROR("formId not napi_object");
537 NapiFormUtil::ThrowParamTypeError(env, "want", "Want");
538 return CreateJsUndefined(env);
539 }
540 if (!AppExecFwk::UnwrapWant(env, argv[PARAM0], asyncCallbackInfo->want)) {
541 HILOG_ERROR("fail convert want");
542 NapiFormUtil::ThrowParamError(env, "Failed to convert want.");
543 return CreateJsUndefined(env);
544 }
545 convertArgc++;
546
547 if (argc > ARGS_SIZE_ONE) {
548 napi_valuetype paramOneType = napi_undefined;
549 napi_typeof(env, argv[PARAM1], ¶mOneType);
550 if (paramOneType == napi_object) {
551 asyncCallbackInfo->withFormBindingData = true;
552 auto formProviderData = std::make_unique<FormProviderData>();
553 std::string formDataStr = GetStringByProp(env, argv[PARAM1], "data");
554 formProviderData->SetDataString(formDataStr);
555 formProviderData->ParseImagesData();
556 asyncCallbackInfo->formProviderData = std::move(formProviderData);
557
558 napi_value nativeProxies = nullptr;
559 napi_get_named_property(env, argv[PARAM1], "proxies", &nativeProxies);
560 if (nativeProxies != nullptr) {
561 ConvertFromDataProxies(env, nativeProxies, asyncCallbackInfo->formDataProxies);
562 }
563 convertArgc++;
564 } else if (paramOneType == napi_function) {
565 asyncCallbackInfo->withFormBindingData = false;
566 } else {
567 HILOG_ERROR("formBindingData not napi_object");
568 NapiFormUtil::ThrowParamTypeError(env, "formBindingData", "formBindingData.FormBindingData");
569 return CreateJsUndefined(env);
570 }
571 }
572
573 NapiAsyncTask::CompleteCallback complete = [asyncCallbackInfo](napi_env env, NapiAsyncTask &task, int32_t status) {
574 int64_t formId = 0;
575 asyncCallbackInfo->want.SetParam(IS_FORM_AGENT, false);
576 ErrCode ret = FormMgr::GetInstance().RequestPublishForm(asyncCallbackInfo->want,
577 asyncCallbackInfo->withFormBindingData, asyncCallbackInfo->formProviderData, formId,
578 asyncCallbackInfo->formDataProxies);
579 if (ret != ERR_OK) {
580 task.Reject(env, NapiFormUtil::CreateErrorByInternalErrorCode(env, ret));
581 return;
582 }
583 std::string formIdStr = std::to_string(formId);
584 napi_value result = nullptr;
585 napi_create_string_utf8(env, formIdStr.c_str(), formIdStr.size(), &result);
586 task.ResolveWithNoError(env, result);
587 };
588 napi_value lastParam = (argc <= convertArgc) ? nullptr : argv[convertArgc];
589 napi_value result = nullptr;
590 NapiAsyncTask::ScheduleWithDefaultQos("JsFormProvider::OnRequestPublishForm",
591 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
592 return result;
593 }
594
ConvertFromDataProxies(napi_env env,napi_value value,std::vector<AppExecFwk::FormDataProxy> & formDataProxies)595 bool JsFormProvider::ConvertFromDataProxies(napi_env env, napi_value value,
596 std::vector<AppExecFwk::FormDataProxy> &formDataProxies)
597 {
598 bool result = false;
599 napi_is_array(env, value, &result);
600 if (value == nullptr || !result) {
601 HILOG_WARN("null jsValue not array");
602 return false;
603 }
604
605 uint32_t length = 0;
606 napi_get_array_length(env, value, &length);
607 napi_value element = nullptr;
608 for (uint32_t i = 0; i < length; i++) {
609 AppExecFwk::FormDataProxy formDataProxy("", "");
610 napi_get_element(env, value, i, &element);
611 if (!ConvertFormDataProxy(env, element, formDataProxy)) {
612 HILOG_ERROR("GetElement from array [%{public}u] error", i);
613 continue;
614 }
615 formDataProxies.push_back(formDataProxy);
616 }
617 return true;
618 }
619
ConvertFormDataProxy(napi_env env,napi_value value,AppExecFwk::FormDataProxy & formDataProxy)620 bool JsFormProvider::ConvertFormDataProxy(napi_env env, napi_value value,
621 AppExecFwk::FormDataProxy &formDataProxy)
622 {
623 napi_valuetype valueType = napi_undefined;
624 napi_typeof(env, value, &valueType);
625 if (value == nullptr || valueType != napi_object) {
626 HILOG_WARN("null jsValue,not object");
627 return false;
628 }
629
630 napi_value key = nullptr;
631 napi_get_named_property(env, value, "key", &key);
632 if (!ConvertFromJsValue(env, key, formDataProxy.key)) {
633 HILOG_ERROR("Parse key error");
634 return false;
635 }
636
637 napi_value subscribeId = nullptr;
638 napi_get_named_property(env, value, "subscriberId", &subscribeId);
639 if (subscribeId != nullptr && !ConvertFromJsValue(env, subscribeId, formDataProxy.subscribeId)) {
640 HILOG_WARN("Parse subscribeId failed, use empty as default value");
641 formDataProxy.subscribeId = "";
642 }
643 HILOG_INFO("key:%{public}s,subscribeId:%{public}s", formDataProxy.key.c_str(),
644 formDataProxy.subscribeId.c_str());
645 return true;
646 }
647
OpenFormEditAbility(napi_env env,napi_callback_info info)648 napi_value JsFormProvider::OpenFormEditAbility(napi_env env, napi_callback_info info)
649 {
650 GET_CB_INFO_AND_CALL(env, info, JsFormProvider, OnOpenFormEditAbility);
651 }
652
OnOpenFormEditAbility(napi_env env,size_t argc,napi_value * argv)653 napi_value JsFormProvider::OnOpenFormEditAbility(napi_env env, size_t argc, napi_value* argv)
654 {
655 HILOG_DEBUG("call");
656 if (!CheckParamNum(env, argc, ARGS_SIZE_TWO, ARGS_SIZE_THREE)) {
657 NapiFormUtil::ThrowParamNumError(env, std::to_string(argc), "2 or 3");
658 return CreateJsUndefined(env);
659 }
660 std::string abilityName;
661 if (!ConvertFromJsValue(env, argv[PARAM0], abilityName)) {
662 HILOG_ERROR("ConvertFromJsValue failed");
663 NapiFormUtil::ThrowParamTypeError(env, "abilityName", "string");
664 return CreateJsUndefined(env);
665 }
666
667 int64_t formId = 0;
668 if (!ConvertFormId(env, argv[PARAM1], formId)) {
669 HILOG_ERROR("ConvertFromJsValue");
670 NapiFormUtil::ThrowParamTypeError(env, "formId", "string");
671 return CreateJsUndefined(env);
672 }
673
674 bool isMainPage = true;
675 if (argc == ARGS_SIZE_THREE) {
676 if (!ConvertFromJsValue(env, argv[PARAM2], isMainPage)) {
677 isMainPage = true;
678 }
679 }
680 HILOG_INFO("OnOpenFormEditAbility abilityName: %{public}s, formId: %{public}" PRId64 "isMainPage: %{public}s",
681 abilityName.c_str(), formId, isMainPage ? "true" : "false");
682 auto ret = FormMgr::GetInstance().OpenFormEditAbility(abilityName, formId, isMainPage);
683 if (ret != ERR_OK) {
684 NapiFormUtil::ThrowByInternalErrorCode(env, ret);
685 }
686 return CreateJsUndefined(env);
687 }
688 } // namespace AbilityRuntime
689 } // namespace OHOS
690