• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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], &paramTwoType);
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], &paramZeroType);
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], &paramZeroType);
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], &paramOneType);
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], &paramOneType);
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], &paramZeroType);
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], &paramOneType);
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