1 /*
2  * Copyright (c) 2021-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 "frameworks/bridge/declarative_frontend/jsview/js_form.h"
17 
18 #include "base/geometry/dimension.h"
19 #include "base/geometry/ng/size_t.h"
20 #include "base/log/ace_scoring_log.h"
21 #include "base/log/log_wrapper.h"
22 #include "base/utils/string_utils.h"
23 #include "bridge/declarative_frontend/jsview/models/form_model_impl.h"
24 #include "core/components_ng/base/view_abstract.h"
25 #include "core/components_ng/pattern/form/form_model_ng.h"
26 #include "frameworks/bridge/declarative_frontend/jsview/js_utils.h"
27 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
28 
29 #if !defined(WEARABLE_PRODUCT)
30 #include "frameworks/core/components/form/form_component.h"
31 #endif
32 
33 namespace OHOS::Ace {
34 
35 std::unique_ptr<FormModel> FormModel::instance_ = nullptr;
36 std::mutex FormModel::mutex_;
37 
GetInstance()38 FormModel* FormModel::GetInstance()
39 {
40     if (!instance_) {
41         std::lock_guard<std::mutex> lock(mutex_);
42         if (!instance_) {
43 #ifdef NG_BUILD
44             instance_.reset(new NG::FormModelNG());
45 #else
46             if (Container::IsCurrentUseNewPipeline()) {
47                 instance_.reset(new NG::FormModelNG());
48             } else {
49                 instance_.reset(new Framework::FormModelImpl());
50             }
51 #endif
52         }
53     }
54     return instance_.get();
55 }
56 
57 } // namespace OHOS::Ace
58 
59 namespace OHOS::Ace::Framework {
60 
Create(const JSCallbackInfo & info)61 void JSForm::Create(const JSCallbackInfo& info)
62 {
63     if (info.Length() == 0 || !info[0]->IsObject()) {
64         return;
65     }
66     auto obj = JSRef<JSObject>::Cast(info[0]);
67     JSRef<JSVal> id = obj->GetProperty("id");
68     JSRef<JSVal> name = obj->GetProperty("name");
69     JSRef<JSVal> bundle = obj->GetProperty("bundle");
70     JSRef<JSVal> ability = obj->GetProperty("ability");
71     JSRef<JSVal> module = obj->GetProperty("module");
72     JSRef<JSVal> dimension = obj->GetProperty("dimension");
73     JSRef<JSVal> temporary = obj->GetProperty("temporary");
74     JSRef<JSVal> wantValue = obj->GetProperty("want");
75     JSRef<JSVal> renderingMode = obj->GetProperty("renderingMode");
76     JSRef<JSVal> shape = obj->GetProperty("shape");
77     RequestFormInfo formInfo;
78     if (id->IsString()) {
79         if (!StringUtils::IsNumber(id->ToString())) {
80             LOGE("Invalid form id : %{public}s", id->ToString().c_str());
81             return;
82         }
83         int64_t inputFormId = StringUtils::StringToLongInt(id->ToString().c_str(), -1);
84         if (inputFormId == -1) {
85             LOGE("StringToLongInt failed : %{public}s", id->ToString().c_str());
86             return;
87         }
88         formInfo.id = inputFormId;
89     } else if (id->IsNumber()) {
90         formInfo.id = id->ToNumber<int64_t>();
91     }
92     LOGI("JSForm Create, info.id: %{public}" PRId64, formInfo.id);
93     formInfo.cardName = name->ToString();
94     formInfo.bundleName = bundle->ToString();
95     formInfo.abilityName = ability->ToString();
96     formInfo.moduleName = module->ToString();
97     if (!dimension->IsNull() && !dimension->IsEmpty()) {
98         formInfo.dimension = dimension->ToNumber<int32_t>();
99     }
100     formInfo.temporary = temporary->ToBoolean();
101     if (!wantValue->IsNull() && wantValue->IsObject()) {
102         formInfo.wantWrap = CreateWantWrapFromNapiValue(wantValue);
103     }
104     if (!renderingMode->IsNull() && !renderingMode->IsEmpty()) {
105         formInfo.renderingMode = renderingMode->ToNumber<int32_t>();
106     }
107     if (!shape->IsNull() && !shape->IsEmpty()) {
108         formInfo.shape = shape->ToNumber<int32_t>();
109     }
110     FormModel::GetInstance()->Create(formInfo);
111 }
112 
SetSize(const JSCallbackInfo & info)113 void JSForm::SetSize(const JSCallbackInfo& info)
114 {
115     JSViewAbstract::JsSize(info);
116 
117     if (info.Length() == 0 || !info[0]->IsObject()) {
118         return;
119     }
120     Dimension width = 0.0_vp;
121     Dimension height = 0.0_vp;
122 
123     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
124     JSRef<JSVal> widthValue = sizeObj->GetProperty("width");
125     if (!widthValue->IsNull() && !widthValue->IsEmpty()) {
126         if (widthValue->IsNumber()) {
127             width = Dimension(widthValue->ToNumber<double>(), DimensionUnit::VP);
128         } else if (widthValue->IsString()) {
129             width = StringUtils::StringToDimension(widthValue->ToString(), true);
130         }
131     }
132 
133     JSRef<JSVal> heightValue = sizeObj->GetProperty("height");
134     if (!heightValue->IsNull() && !heightValue->IsEmpty()) {
135         if (heightValue->IsNumber()) {
136             height = Dimension(heightValue->ToNumber<double>(), DimensionUnit::VP);
137         } else if (heightValue->IsString()) {
138             height = StringUtils::StringToDimension(heightValue->ToString(), true);
139         }
140     }
141     FormModel::GetInstance()->SetSize(width, height);
142 }
143 
SetDimension(int32_t value)144 void JSForm::SetDimension(int32_t value)
145 {
146     FormModel::GetInstance()->SetDimension(value);
147 }
148 
AllowUpdate(const JSCallbackInfo & info)149 void JSForm::AllowUpdate(const JSCallbackInfo& info)
150 {
151     if (info.Length() <= 0 || !info[0]->IsBoolean()) {
152         return;
153     }
154 
155     auto allowUpdate = info[0]->ToBoolean();
156     FormModel::GetInstance()->AllowUpdate(allowUpdate);
157 }
158 
SetVisibility(const JSCallbackInfo & info)159 void JSForm::SetVisibility(const JSCallbackInfo& info)
160 {
161     if (info.Length() <= 0 || !info[0]->IsNumber()) {
162         return;
163     }
164 
165     auto type = info[0]->ToNumber<int32_t>();
166     FormModel::GetInstance()->SetVisibility(VisibleType(type));
167 }
168 
SetModuleName(const JSCallbackInfo & info)169 void JSForm::SetModuleName(const JSCallbackInfo& info)
170 {
171     if (info.Length() <= 0 || !info[0]->IsString()) {
172         return;
173     }
174 
175     auto moduleName = info[0]->ToString();
176     FormModel::GetInstance()->SetModuleName(moduleName);
177 }
178 
JsOnAcquired(const JSCallbackInfo & info)179 void JSForm::JsOnAcquired(const JSCallbackInfo& info)
180 {
181     if (info[0]->IsFunction()) {
182         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
183         auto onAcquired = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
184             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
185             ACE_SCORING_EVENT("Form.onAcquired");
186             std::vector<std::string> keys = { "id", "idString" };
187             func->Execute(keys, param);
188         };
189         FormModel::GetInstance()->SetOnAcquired(std::move(onAcquired));
190     }
191 }
192 
JsOnError(const JSCallbackInfo & info)193 void JSForm::JsOnError(const JSCallbackInfo& info)
194 {
195     if (info[0]->IsFunction()) {
196         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
197         auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
198             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
199             ACE_SCORING_EVENT("Form.onError");
200             std::vector<std::string> keys = { "errcode", "msg" };
201             func->Execute(keys, param);
202         };
203         FormModel::GetInstance()->SetOnError(std::move(onError));
204     }
205 }
206 
JsOnUninstall(const JSCallbackInfo & info)207 void JSForm::JsOnUninstall(const JSCallbackInfo& info)
208 {
209     if (info[0]->IsFunction()) {
210         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
211         auto onUninstall = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
212             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
213             ACE_SCORING_EVENT("Form.onUninstall");
214             std::vector<std::string> keys = { "id", "idString" };
215             func->Execute(keys, param);
216         };
217         FormModel::GetInstance()->SetOnUninstall(std::move(onUninstall));
218     }
219 }
220 
JsOnRouter(const JSCallbackInfo & info)221 void JSForm::JsOnRouter(const JSCallbackInfo& info)
222 {
223     if (info[0]->IsFunction()) {
224         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
225         auto onRouter = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
226             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
227             ACE_SCORING_EVENT("Form.onRouter");
228             std::vector<std::string> keys = { "action" };
229             func->Execute(keys, param);
230         };
231         FormModel::GetInstance()->SetOnRouter(std::move(onRouter));
232     }
233 }
234 
JsOnLoad(const JSCallbackInfo & info)235 void JSForm::JsOnLoad(const JSCallbackInfo& info)
236 {
237     if (info[0]->IsFunction()) {
238         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
239         auto onLoad = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
240             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
241             ACE_SCORING_EVENT("Form.onLoad");
242             std::vector<std::string> keys;
243             func->Execute(keys, param);
244         };
245         FormModel::GetInstance()->SetOnLoad(std::move(onLoad));
246     }
247 }
248 
JsObscured(const JSCallbackInfo & info)249 void JSForm::JsObscured(const JSCallbackInfo& info)
250 {
251     if (info[0]->IsUndefined()) {
252         LOGE("Obscured reasons undefined");
253         return;
254     }
255     if (!info[0]->IsArray()) {
256         LOGE("Obscured reasons not Array");
257         return;
258     }
259     auto obscuredArray = JSRef<JSArray>::Cast(info[0]);
260     size_t size = obscuredArray->Length();
261     std::vector<ObscuredReasons> reasons;
262     reasons.reserve(size);
263     for (size_t i = 0; i < size; ++i) {
264         JSRef<JSVal> reason = obscuredArray->GetValueAt(i);
265         if (reason->IsNumber()) {
266             reasons.push_back(static_cast<ObscuredReasons>(reason->ToNumber<int32_t>()));
267         }
268     }
269     FormModel::GetInstance()->SetObscured(reasons);
270 }
271 
JSBind(BindingTarget globalObj)272 void JSForm::JSBind(BindingTarget globalObj)
273 {
274     JSClass<JSForm>::Declare("FormComponent");
275     MethodOptions opt = MethodOptions::NONE;
276     JSClass<JSForm>::StaticMethod("create", &JSForm::Create, opt);
277     JSClass<JSForm>::StaticMethod("size", &JSForm::SetSize, opt);
278     JSClass<JSForm>::StaticMethod("dimension", &JSForm::SetDimension, opt);
279     JSClass<JSForm>::StaticMethod("allowUpdate", &JSForm::AllowUpdate, opt);
280     JSClass<JSForm>::StaticMethod("visibility", &JSForm::SetVisibility, opt);
281     JSClass<JSForm>::StaticMethod("moduleName", &JSForm::SetModuleName, opt);
282     JSClass<JSForm>::StaticMethod("clip", &JSViewAbstract::JsClip, opt);
283     JSClass<JSForm>::StaticMethod("obscured", &JSForm::JsObscured);
284 
285     JSClass<JSForm>::StaticMethod("onAcquired", &JSForm::JsOnAcquired);
286     JSClass<JSForm>::StaticMethod("onError", &JSForm::JsOnError);
287     JSClass<JSForm>::StaticMethod("onUninstall", &JSForm::JsOnUninstall);
288     JSClass<JSForm>::StaticMethod("onRouter", &JSForm::JsOnRouter);
289     JSClass<JSForm>::StaticMethod("onLoad", &JSForm::JsOnLoad);
290     JSClass<JSForm>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
291     JSClass<JSForm>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
292     JSClass<JSForm>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
293     JSClass<JSForm>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
294     JSClass<JSForm>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
295     JSClass<JSForm>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
296     JSClass<JSForm>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
297     JSClass<JSForm>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
298 
299     JSClass<JSForm>::InheritAndBind<JSViewAbstract>(globalObj);
300 }
301 
302 } // namespace OHOS::Ace::Framework
303