• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "js_form_provider.h"
17 
18 #include <cinttypes>
19 #include <vector>
20 
21 #include "form_mgr_errors.h"
22 #include "form_mgr.h"
23 #include "js_form_info_util.h"
24 #include "js_runtime_utils.h"
25 #include "hilog_wrapper.h"
26 #include "napi_common_util.h"
27 #include "napi_common_want.h"
28 #include "napi_form_util.h"
29 #include "napi/native_api.h"
30 #include "napi/native_node_api.h"
31 #include "runtime.h"
32 
33 namespace OHOS {
34 namespace AbilityRuntime {
35 using namespace OHOS;
36 using namespace OHOS::AAFwk;
37 using namespace OHOS::AppExecFwk;
38 namespace {
39 constexpr size_t ARGS_SIZE_ONE = 1;
40 constexpr size_t ARGS_SIZE_TWO = 2;
41 constexpr size_t ARGS_SIZE_THREE = 3;
42 
ConvertFormInfoFilterThrow(NativeEngine & engine,NativeValue * jsValue,AppExecFwk::FormInfoFilter & formInfoFilter)43 bool ConvertFormInfoFilterThrow(NativeEngine &engine, NativeValue *jsValue, AppExecFwk::FormInfoFilter &formInfoFilter)
44 {
45     if (jsValue->TypeOf() != NATIVE_OBJECT) {
46         HILOG_ERROR("%{public}s, an object is expected, but an argument of different type is passed in.", __func__);
47         NapiFormUtil::ThrowParamTypeError(engine, "filter", "formInfo.FormInfoFilter");
48         return false;
49     }
50 
51     NativeObject *nativeObject = ConvertNativeValueTo<NativeObject>(jsValue);
52     if (nativeObject == nullptr) {
53         HILOG_ERROR("%{public}s called, nativeObject is nullptr.", __func__);
54         NapiFormUtil::ThrowParamError(engine, "Failed to convert FormInfoFilter.");
55         return false;
56     }
57     NativeValue *nativeDataValue = nativeObject->GetProperty("moduleName");
58     if (nativeDataValue == nullptr || (nativeDataValue->TypeOf() != NATIVE_UNDEFINED &&
59                                        !ConvertFromJsValue(engine, nativeDataValue, formInfoFilter.moduleName))) {
60         HILOG_ERROR("%{public}s called, convert nativeDataValue failed.", __func__);
61         NapiFormUtil::ThrowParamError(engine, "Failed to convert FormInfoFilter.");
62         return false;
63     }
64     HILOG_INFO("%{public}s called, module name is %{public}s.", __func__, formInfoFilter.moduleName.c_str());
65 
66     return true;
67 }
68 }
69 
GetStringByProp(napi_env env,napi_value value,const std::string & prop)70 static std::string GetStringByProp(napi_env env, napi_value value, const std::string &prop)
71 {
72     std::string result;
73     bool propExist = false;
74     napi_value propValue = nullptr;
75     napi_valuetype valueType = napi_undefined;
76     napi_has_named_property(env, value, prop.c_str(), &propExist);
77     if (!propExist) {
78         HILOG_ERROR("%{public}s, prop[%{public}s] not exist.", __func__, prop.c_str());
79         return result;
80     }
81     napi_get_named_property(env, value, prop.c_str(), &propValue);
82     if (propValue == nullptr) {
83         HILOG_ERROR("%{public}s, prop[%{public}s] get failed.", __func__, prop.c_str());
84         return result;
85     }
86     napi_typeof(env, propValue, &valueType);
87     if (valueType != napi_string) {
88         HILOG_ERROR("%{public}s, prop[%{public}s] is not napi_string.", __func__, prop.c_str());
89         return result;
90     }
91     size_t size = 0;
92     if (napi_get_value_string_utf8(env, propValue, nullptr, 0, &size) != napi_ok) {
93         HILOG_ERROR("%{public}s, prop[%{public}s] get size failed.", __func__, prop.c_str());
94         return result;
95     }
96     result.reserve(size + 1);
97     result.resize(size);
98     if (napi_get_value_string_utf8(env, propValue, result.data(), (size + 1), &size) != napi_ok) {
99         HILOG_ERROR("%{public}s, prop[%{public}s] get value failed.", __func__, prop.c_str());
100         return "";
101     }
102     return result;
103 }
104 
Finalizer(NativeEngine * engine,void * data,void * hint)105 void JsFormProvider::Finalizer(NativeEngine *engine, void *data, void *hint)
106 {
107     HILOG_INFO("JsFormProvider::Finalizer is called");
108     std::unique_ptr<JsFormProvider>(static_cast<JsFormProvider *>(data));
109 }
110 
GetFormsInfo(NativeEngine * engine,NativeCallbackInfo * info)111 NativeValue *JsFormProvider::GetFormsInfo(NativeEngine *engine, NativeCallbackInfo *info)
112 {
113     JsFormProvider *me = CheckParamsAndGetThis<JsFormProvider>(engine, info);
114     return (me != nullptr) ? me->OnGetFormsInfo(*engine, *info) : nullptr;
115 }
116 
OnGetFormsInfo(NativeEngine & engine,NativeCallbackInfo & info)117 NativeValue *JsFormProvider::OnGetFormsInfo(NativeEngine &engine, NativeCallbackInfo &info)
118 {
119     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
120     if (info.argc > ARGS_SIZE_TWO) {
121         HILOG_ERROR("%{public}s, wrong number of arguments.", __func__);
122         NapiFormUtil::ThrowParamNumError(engine, std::to_string(info.argc), "0, 1 or 2");
123         return engine.CreateUndefined();
124     }
125 
126     size_t convertArgc = 0;
127     FormInfoFilter formInfoFilter;
128     if (info.argc > 0 && info.argv[0]->TypeOf() != NATIVE_FUNCTION) {
129         if (!ConvertFormInfoFilterThrow(engine, info.argv[0], formInfoFilter)) {
130             HILOG_ERROR("%{public}s, convert form info filter failed.", __func__);
131             return engine.CreateUndefined();
132         }
133         convertArgc++;
134     }
135 
136     AsyncTask::CompleteCallback complete =
137         [formInfoFilter](NativeEngine &engine, AsyncTask &task, int32_t status) {
138             std::vector<FormInfo> formInfos;
139             auto ret = FormMgr::GetInstance().GetFormsInfo(formInfoFilter, formInfos);
140             if (ret != ERR_OK) {
141                 task.Reject(engine, NapiFormUtil::CreateErrorByInternalErrorCode(engine, ret));
142                 return;
143             }
144             task.ResolveWithNoError(engine, CreateJsFormInfoArray(engine, formInfos));
145         };
146 
147     NativeValue *lastParam = (info.argc <= convertArgc) ? nullptr : info.argv[convertArgc];
148     NativeValue *result = nullptr;
149     AsyncTask::Schedule("JsFormProvider::OnGetFormsInfo",
150         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
151     return result;
152 }
153 
SetFormNextRefreshTime(NativeEngine * engine,NativeCallbackInfo * info)154 NativeValue *JsFormProvider::SetFormNextRefreshTime(NativeEngine *engine, NativeCallbackInfo *info)
155 {
156     JsFormProvider *me = CheckParamsAndGetThis<JsFormProvider>(engine, info);
157     return (me != nullptr) ? me->OnSetFormNextRefreshTime(*engine, *info) : nullptr;
158 }
159 
OnSetFormNextRefreshTime(NativeEngine & engine,NativeCallbackInfo & info)160 NativeValue *JsFormProvider::OnSetFormNextRefreshTime(NativeEngine &engine, NativeCallbackInfo &info)
161 {
162     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
163     if (info.argc < ARGS_SIZE_TWO || info.argc > ARGS_SIZE_THREE) {
164         HILOG_ERROR("wrong number of arguments.");
165         NapiFormUtil::ThrowParamNumError(engine, std::to_string(info.argc), "2 or 3");
166         return engine.CreateUndefined();
167     }
168     if (info.argv[PARAM0]->TypeOf() != NATIVE_STRING) {
169         HILOG_ERROR("formId is not napi_string.");
170         NapiFormUtil::ThrowParamTypeError(engine, "formId", "string");
171         return engine.CreateUndefined();
172     }
173     int64_t formId = 0;
174     std::string strFormId;
175     bool confirm = ConvertFromJsValue(engine, info.argv[PARAM0], strFormId);
176     if (!confirm) {
177         HILOG_ERROR("ConvertFromJsValue failed.");
178         NapiFormUtil::ThrowParamTypeError(engine, "formId", "string");
179         return engine.CreateUndefined();
180     }
181     if (!ConvertStringToInt64(strFormId, formId)) {
182         HILOG_ERROR("convert form string failed.");
183         NapiFormUtil::ThrowParamError(engine, "Failed to convert formId.");
184         return engine.CreateUndefined();
185     }
186     if (info.argv[PARAM1]->TypeOf() != NATIVE_NUMBER) {
187         NapiFormUtil::ThrowParamTypeError(engine, "minute", "number");
188         return engine.CreateUndefined();
189     }
190     int32_t time;
191     bool res = ConvertFromJsValue(engine, info.argv[PARAM1], time);
192     if (!res) {
193         HILOG_ERROR("ConvertFromJsValue failed.");
194         NapiFormUtil::ThrowParamTypeError(engine, "minute", "number");
195         return engine.CreateUndefined();
196     }
197     AsyncTask::CompleteCallback complete = [formId, time](NativeEngine &engine, AsyncTask &task, int32_t status) {
198         int32_t ret = FormMgr::GetInstance().SetNextRefreshTime(formId, time);
199         if (ret != ERR_OK) {
200             task.Reject(engine, NapiFormUtil::CreateErrorByInternalErrorCode(engine, ret));
201             return;
202         }
203         task.ResolveWithNoError(engine, engine.CreateUndefined());
204     };
205     NativeValue *lastParam = (info.argc == ARGS_SIZE_THREE) ? info.argv[PARAM2] : nullptr;
206     NativeValue *result = nullptr;
207     AsyncTask::Schedule("JsFormProvider::OnSetFormNextRefreshTime",
208         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
209     return result;
210 }
211 
UpdateForm(NativeEngine * engine,NativeCallbackInfo * info)212 NativeValue *JsFormProvider::UpdateForm(NativeEngine *engine, NativeCallbackInfo *info)
213 {
214     JsFormProvider *me = CheckParamsAndGetThis<JsFormProvider>(engine, info);
215     return (me != nullptr) ? me->OnUpdateForm(*engine, *info) : nullptr;
216 }
217 
OnUpdateForm(NativeEngine & engine,NativeCallbackInfo & info)218 NativeValue *JsFormProvider::OnUpdateForm(NativeEngine &engine, NativeCallbackInfo &info)
219 {
220     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
221     auto env = reinterpret_cast<napi_env>(&engine);
222     if (info.argc < ARGS_SIZE_TWO || info.argc > ARGS_SIZE_THREE) {
223         HILOG_ERROR("wrong number of arguments.");
224         NapiFormUtil::ThrowParamNumError(engine, std::to_string(info.argc), "2 or 3");
225         return engine.CreateUndefined();
226     }
227     if (info.argv[PARAM0]->TypeOf() != NATIVE_STRING) {
228         HILOG_ERROR("formId is not napi_string.");
229         NapiFormUtil::ThrowParamTypeError(engine, "formId", "string");
230         return engine.CreateUndefined();
231     }
232     int64_t formId = 0;
233     std::string strFormId;
234     bool confirm = ConvertFromJsValue(engine, info.argv[PARAM0], strFormId);
235     if (!confirm) {
236         HILOG_ERROR("ConvertFromJsValue failed.");
237         NapiFormUtil::ThrowParamTypeError(engine, "formId", "string");
238         return engine.CreateUndefined();
239     }
240     if (!ConvertStringToInt64(strFormId, formId)) {
241         HILOG_ERROR("convert form string failed.");
242         NapiFormUtil::ThrowParamError(engine, "Failed to convert formId.");
243         return engine.CreateUndefined();
244     }
245     if (info.argv[PARAM1]->TypeOf() != NATIVE_OBJECT) {
246         HILOG_ERROR("formBindingData is not napi_object.");
247         NapiFormUtil::ThrowParamTypeError(engine, "formBindingData", "formBindingData.FormBindingData");
248         return engine.CreateUndefined();
249     }
250     auto formProviderData = std::make_shared<OHOS::AppExecFwk::FormProviderData>();
251     auto arg1 = reinterpret_cast<napi_value>(info.argv[PARAM1]);
252     std::string formDataStr = GetStringByProp(env, arg1, "data");
253     formProviderData->SetDataString(formDataStr);
254     formProviderData->ParseImagesData();
255     AsyncTask::CompleteCallback complete =
256         [formId, data = formProviderData](NativeEngine &engine, AsyncTask &task, int32_t status) {
257             int32_t ret = FormMgr::GetInstance().UpdateForm(formId, *data);
258             if (ret != ERR_OK) {
259                 task.Reject(engine, NapiFormUtil::CreateErrorByInternalErrorCode(engine, ret));
260                 return;
261             }
262             task.ResolveWithNoError(engine, engine.CreateUndefined());
263         };
264     NativeValue *lastParam = (info.argc == ARGS_SIZE_THREE) ? info.argv[PARAM2] : nullptr;
265     NativeValue *result = nullptr;
266     AsyncTask::Schedule("JsFormProvider::OnUpdateForm",
267         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
268     return result;
269 }
270 
IsRequestPublishFormSupported(NativeEngine * engine,NativeCallbackInfo * info)271 NativeValue *JsFormProvider::IsRequestPublishFormSupported(NativeEngine *engine, NativeCallbackInfo *info)
272 {
273     JsFormProvider *me = CheckParamsAndGetThis<JsFormProvider>(engine, info);
274     return (me != nullptr) ? me->OnIsRequestPublishFormSupported(*engine, *info) : nullptr;
275 }
276 
OnIsRequestPublishFormSupported(NativeEngine & engine,const NativeCallbackInfo & info)277 NativeValue *JsFormProvider::OnIsRequestPublishFormSupported(NativeEngine &engine, const NativeCallbackInfo &info)
278 {
279     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
280     if (info.argc > ARGS_SIZE_ONE) {
281         HILOG_ERROR("wrong number of arguments.");
282         NapiFormUtil::ThrowParamNumError(engine, std::to_string(info.argc), "0 or 1");
283         return engine.CreateUndefined();
284     }
285 
286     AsyncTask::CompleteCallback complete = [](NativeEngine &engine, AsyncTask &task, int32_t status) {
287         bool value = FormMgr::GetInstance().IsRequestPublishFormSupported();
288         task.ResolveWithNoError(engine, engine.CreateBoolean(value));
289     };
290     NativeValue *lastParam = (info.argc == ARGS_SIZE_ONE) ? info.argv[PARAM0] : nullptr;
291     NativeValue *result = nullptr;
292     AsyncTask::Schedule("JsFormProvider::OnIsRequestPublishFormSupported",
293         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
294     return result;
295 }
296 
RequestPublishForm(NativeEngine * engine,NativeCallbackInfo * info)297 NativeValue *JsFormProvider::RequestPublishForm(NativeEngine *engine, NativeCallbackInfo *info)
298 {
299     JsFormProvider *me = CheckParamsAndGetThis<JsFormProvider>(engine, info);
300     return (me != nullptr) ? me->OnRequestPublishForm(*engine, *info) : nullptr;
301 }
302 
OnRequestPublishForm(NativeEngine & engine,NativeCallbackInfo & info)303 NativeValue *JsFormProvider::OnRequestPublishForm(NativeEngine &engine, NativeCallbackInfo &info)
304 {
305     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
306     auto env = reinterpret_cast<napi_env>(&engine);
307     if (info.argc < ARGS_SIZE_ONE || info.argc > ARGS_SIZE_THREE) {
308         HILOG_ERROR("wrong number of arguments.");
309         NapiFormUtil::ThrowParamNumError(engine, std::to_string(info.argc), "1, 2 or 3");
310         return engine.CreateUndefined();
311     }
312 
313     auto asyncCallbackInfo = std::make_shared<RequestPublishFormCallbackInfo>();
314     decltype(info.argc) convertArgc = 0;
315     if (info.argv[PARAM0]->TypeOf() != NATIVE_OBJECT) {
316         HILOG_ERROR("formId is not napi_object.");
317         NapiFormUtil::ThrowParamTypeError(engine, "want", "Want");
318         return engine.CreateUndefined();
319     }
320     if (!AppExecFwk::UnwrapWant(env, reinterpret_cast<napi_value>(info.argv[PARAM0]), asyncCallbackInfo->want)) {
321         HILOG_ERROR("Failed to convert want.");
322         NapiFormUtil::ThrowParamError(engine, "Failed to convert want.");
323         return engine.CreateUndefined();
324     }
325     convertArgc++;
326 
327     if (info.argc > ARGS_SIZE_ONE) {
328         asyncCallbackInfo->withFormBindingData = true;
329         if (info.argv[PARAM1]->TypeOf() != NATIVE_OBJECT) {
330             HILOG_ERROR("formBindingData is not napi_object.");
331             NapiFormUtil::ThrowParamTypeError(engine, "formBindingData", "formBindingData.FormBindingData");
332             return engine.CreateUndefined();
333         }
334         auto formProviderData = std::make_unique<FormProviderData>();
335         auto arg1 = reinterpret_cast<napi_value>(info.argv[PARAM1]);
336         std::string formDataStr = GetStringByProp(env, arg1, "data");
337         formProviderData->SetDataString(formDataStr);
338         formProviderData->ParseImagesData();
339         asyncCallbackInfo->formProviderData = std::move(formProviderData);
340         convertArgc++;
341     }
342 
343     AsyncTask::CompleteCallback complete = [asyncCallbackInfo](NativeEngine &engine, AsyncTask &task, int32_t status) {
344         int64_t formId = 0;
345         ErrCode ret = FormMgr::GetInstance().RequestPublishForm(asyncCallbackInfo->want,
346             asyncCallbackInfo->withFormBindingData, asyncCallbackInfo->formProviderData, formId);
347         if (ret != ERR_OK) {
348             task.Reject(engine, NapiFormUtil::CreateErrorByInternalErrorCode(engine, ret));
349             return;
350         }
351         std::string formIdStr = std::to_string(formId);
352         task.ResolveWithNoError(engine, engine.CreateString(formIdStr.c_str(), formIdStr.size()));
353     };
354     NativeValue *lastParam = (info.argc <= convertArgc) ? nullptr : info.argv[convertArgc];
355     NativeValue *result = nullptr;
356     AsyncTask::Schedule("JsFormProvider::OnRequestPublishForm",
357         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
358     return result;
359 }
360 }  // namespace AbilityRuntime
361 }  // namespace OHOS
362