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