1 /*
2  * Copyright (c) 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 "form_renderer_group.h"
17 
18 #include "configuration.h"
19 #include "form_renderer.h"
20 #include "form_renderer_hilog.h"
21 
22 namespace OHOS {
23 namespace Ace {
24 namespace {
25 constexpr char FORM_RENDERER_COMP_ID[] = "ohos.extra.param.key.form_comp_id";
26 constexpr char FORM_RENDER_STATE[] = "ohos.extra.param.key.form_render_state";
27 }
Create(const std::shared_ptr<OHOS::AbilityRuntime::Context> context,const std::shared_ptr<OHOS::AbilityRuntime::Runtime> runtime,std::weak_ptr<OHOS::AppExecFwk::EventHandler> eventHandler)28 std::shared_ptr<FormRendererGroup> FormRendererGroup::Create(
29     const std::shared_ptr<OHOS::AbilityRuntime::Context> context,
30     const std::shared_ptr<OHOS::AbilityRuntime::Runtime> runtime,
31     std::weak_ptr<OHOS::AppExecFwk::EventHandler> eventHandler)
32 {
33     return std::make_shared<FormRendererGroup>(context, runtime, eventHandler);
34 }
35 
FormRendererGroup(const std::shared_ptr<OHOS::AbilityRuntime::Context> context,const std::shared_ptr<OHOS::AbilityRuntime::Runtime> runtime,std::weak_ptr<OHOS::AppExecFwk::EventHandler> eventHandler)36 FormRendererGroup::FormRendererGroup(
37     const std::shared_ptr<OHOS::AbilityRuntime::Context> context,
38     const std::shared_ptr<OHOS::AbilityRuntime::Runtime> runtime,
39     std::weak_ptr<OHOS::AppExecFwk::EventHandler> eventHandler)
40     : context_(context), runtime_(runtime), eventHandler_(eventHandler) {}
41 
~FormRendererGroup()42 FormRendererGroup::~FormRendererGroup()
43 {
44     DeleteForm();
45 }
46 
AddForm(const OHOS::AAFwk::Want & want,const OHOS::AppExecFwk::FormJsInfo & formJsInfo)47 void FormRendererGroup::AddForm(const OHOS::AAFwk::Want& want, const OHOS::AppExecFwk::FormJsInfo& formJsInfo)
48 {
49     auto compId = want.GetStringParam(FORM_RENDERER_COMP_ID);
50     currentCompId_ = compId;
51     FormRequest formRequest;
52     formRequest.compId = compId;
53     formRequest.want = want;
54     formRequest.formJsInfo = formJsInfo;
55     auto info = std::find_if(
56         formRequests_.begin(), formRequests_.end(), formRequest);
57     if (info != formRequests_.end()) {
58         *info = formRequest;
59     } else {
60         formRequests_.emplace_back(formRequest);
61     }
62     bool isVerified = want.GetBoolParam(FORM_RENDER_STATE, false);
63     if (isVerified) {
64         HILOG_DEBUG("The user is verified, start rendering form.");
65         InnerAddForm(formRequest);
66         return;
67     }
68     HILOG_INFO("The user is not verified at this time, can not render the form now.");
69     PreInitAddForm(formRequest);
70 }
71 
PreInitAddForm(const FormRequest & formRequest)72 void FormRendererGroup::PreInitAddForm(const FormRequest& formRequest)
73 {
74     HILOG_DEBUG("called");
75     if (initState_ != FormRendererInitState::UNINITIALIZED) {
76         HILOG_WARN("no need to pre init again");
77         return;
78     }
79     auto compId = formRequest.compId;
80     OHOS::AAFwk::Want want = formRequest.want;
81     AppExecFwk::FormJsInfo formJsInfo = formRequest.formJsInfo;
82     if (formRenderer_ != nullptr) {
83         HILOG_WARN("no need to pre init");
84         return;
85     }
86     formRenderer_ = std::make_shared<FormRenderer>(context_, runtime_, eventHandler_);
87     if (!formRenderer_) {
88         HILOG_ERROR("create form render failed");
89         return;
90     }
91     HILOG_INFO("compId is %{public}s. formId is %{public}s", compId.c_str(),
92         std::to_string(formJsInfo.formId).c_str());
93     formRenderer_->PreInitAddForm(want, formJsInfo);
94     initState_ = FormRendererInitState::PRE_INITIALIZED;
95 }
96 
OnUnlock()97 void FormRendererGroup::OnUnlock()
98 {
99     HILOG_INFO("The user is verified, OnUnlock called.");
100     FormRequest currentFormRequest;
101     bool hasValidRequest = false;
102     for (auto& formRequest : formRequests_) {
103         if (currentCompId_ == formRequest.compId) {
104             currentFormRequest = formRequest;
105             formRequest.want.SetParam(FORM_RENDER_STATE, true);
106             hasValidRequest = true;
107         }
108     }
109 
110     if (!hasValidRequest) {
111         HILOG_ERROR("Without valid form requests, current compId is %{public}s", currentCompId_.c_str());
112         return;
113     }
114     InnerAddForm(currentFormRequest);
115 }
116 
SetVisibleChange(bool isVisible)117 void FormRendererGroup::SetVisibleChange(bool isVisible)
118 {
119     if (formRenderer_ == nullptr) {
120         HILOG_ERROR("SetVisibleChange failed, formRenderer is null");
121         return;
122     }
123     formRenderer_->SetVisibleChange(isVisible);
124 }
125 
InnerAddForm(const FormRequest & formRequest)126 void FormRendererGroup::InnerAddForm(const FormRequest& formRequest)
127 {
128     HILOG_DEBUG("InnerAddForm called");
129     auto compId = formRequest.compId;
130     OHOS::AAFwk::Want want = formRequest.want;
131     AppExecFwk::FormJsInfo formJsInfo = formRequest.formJsInfo;
132     if (formRenderer_ == nullptr || initState_ == FormRendererInitState::UNINITIALIZED) {
133         formRenderer_ = std::make_shared<FormRenderer>(context_, runtime_, eventHandler_);
134         if (!formRenderer_) {
135             HILOG_ERROR("InnerAddForm create form render failed");
136             return;
137         }
138         HILOG_INFO("InnerAddForm compId is %{public}s. formId is %{public}s, formJsInfo.formData.size is %{public}zu",
139             compId.c_str(),
140             std::to_string(formJsInfo.formId).c_str(),
141             formJsInfo.formData.size());
142         formRenderer_->AddForm(want, formJsInfo);
143         initState_ = FormRendererInitState::INITIALIZED;
144     } else if (initState_ == FormRendererInitState::PRE_INITIALIZED) {
145         HILOG_INFO("RunFormPage compId is %{public}s. formId is %{public}s, formJsInfo.formData.size is %{public}zu",
146             compId.c_str(),
147             std::to_string(formJsInfo.formId).c_str(),
148             formJsInfo.formData.size());
149         formRenderer_->RunFormPage(want, formJsInfo);
150         initState_ = FormRendererInitState::INITIALIZED;
151     } else { // initState_ == FormRendererInitState::INITIALIZED
152         HILOG_INFO("AttachForm compId is %{public}s, formRequests size is %{public}s, \
153             formJsInfo.formData.size is %{public}zu",
154             compId.c_str(),
155             std::to_string(formRequests_.size()).c_str(),
156             formJsInfo.formData.size());
157         formRenderer_->AttachForm(want, formJsInfo);
158     }
159 }
160 
ReloadForm(const AppExecFwk::FormJsInfo & formJsInfo)161 void FormRendererGroup::ReloadForm(const AppExecFwk::FormJsInfo& formJsInfo)
162 {
163     if (formRenderer_ == nullptr) {
164         HILOG_ERROR("ReloadForm failed, formRenderer is null");
165         return;
166     }
167 
168     formRenderer_->ReloadForm(formJsInfo.formSrc);
169     for (auto &formRequest : formRequests_) {
170         bool allDynamic = formJsInfo.isDynamic && formRequest.isDynamic;
171         if (!allDynamic && currentCompId_ == formRequest.compId) {
172             HILOG_INFO("SurfaceReuse due to change to static card when curCompId is %{public}s.",
173                 formRequest.compId.c_str());
174             formRenderer_->OnSurfaceReuse(formJsInfo);
175         }
176         formRequest.formJsInfo = formJsInfo;
177         formRequest.isDynamic = formJsInfo.isDynamic;
178     }
179 }
180 
UpdateFormSizeOfFormRequests(double width,double height,float borderWidth)181 void FormRendererGroup::UpdateFormSizeOfFormRequests(double width, double height, float borderWidth)
182 {
183     for (auto iter = formRequests_.begin(); iter != formRequests_.end(); ++iter) {
184         iter->want.SetParam(OHOS::AppExecFwk::Constants::PARAM_FORM_WIDTH_KEY, static_cast<double>(width));
185         iter->want.SetParam(OHOS::AppExecFwk::Constants::PARAM_FORM_HEIGHT_KEY, static_cast<double>(height));
186         iter->want.SetParam(OHOS::AppExecFwk::Constants::PARAM_FORM_BORDER_WIDTH_KEY, static_cast<float>(borderWidth));
187     }
188     if (formRenderer_ != nullptr) {
189         formRenderer_->UpdateFormSize(width, height, borderWidth);
190     } else {
191         HILOG_WARN("formRenderer is null");
192     }
193 }
194 
UpdateForm(const OHOS::AppExecFwk::FormJsInfo & formJsInfo)195 void FormRendererGroup::UpdateForm(const OHOS::AppExecFwk::FormJsInfo& formJsInfo)
196 {
197     HILOG_INFO("UpdateForm formId %{public}s.", std::to_string(formJsInfo.formId).c_str());
198     if (formRenderer_ == nullptr) {
199         HILOG_ERROR("UpdateForm failed, formRenderer is null");
200         return;
201     }
202     formRenderer_->UpdateForm(formJsInfo);
203 }
204 
DeleteForm(const std::string & compId)205 void FormRendererGroup::DeleteForm(const std::string& compId)
206 {
207     HILOG_INFO("DeleteForm compId is %{public}s, currentCompId is %{public}s, formRequests size is %{public}s.",
208         compId.c_str(), currentCompId_.c_str(), std::to_string(formRequests_.size()).c_str());
209 
210     for (auto iter = formRequests_.begin(); iter != formRequests_.end(); ++iter) {
211         if (iter->compId == compId) {
212             formRequests_.erase(iter);
213             break;
214         }
215     }
216 
217     if (compId != currentCompId_) {
218         return;
219     }
220 
221     if (formRequests_.empty()) {
222         HILOG_INFO("Release renderer obj due to formRequests is empty.");
223         DeleteForm();
224         return;
225     }
226 
227     FormRequest request = formRequests_.back();
228     currentCompId_ = request.compId;
229     HILOG_INFO("RestoreForm compId is %{public}s.", currentCompId_.c_str());
230     if (formRenderer_ == nullptr) {
231         HILOG_INFO("FormRenderer has destory");
232         return;
233     }
234     formRenderer_->AttachForm(request.want, request.formJsInfo);
235 }
236 
IsFormRequestsEmpty()237 bool FormRendererGroup::IsFormRequestsEmpty()
238 {
239     return formRequests_.empty();
240 }
241 
GetAllRendererFormRequests() const242 const std::vector<FormRequest>& FormRendererGroup::GetAllRendererFormRequests() const
243 {
244     return formRequests_;
245 }
246 
GetOrderedAndCurrentCompIds() const247 std::pair<std::vector<std::string>, std::string> FormRendererGroup::GetOrderedAndCurrentCompIds() const
248 {
249     std::vector<std::string> orderedCompIds;
250     for (auto formRequest: formRequests_) {
251         orderedCompIds.emplace_back(formRequest.compId);
252     }
253     return std::make_pair(orderedCompIds, currentCompId_);
254 }
255 
DeleteForm()256 void FormRendererGroup::DeleteForm()
257 {
258     if (formRenderer_ == nullptr) {
259         HILOG_INFO("FormRenderer has destory");
260         return;
261     }
262     formRenderer_->Destroy();
263     formRenderer_ = nullptr;
264     formRequests_.clear();
265 }
266 
UpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)267 void FormRendererGroup::UpdateConfiguration(
268     const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
269 {
270     if (!config) {
271         HILOG_ERROR("UpdateConfiguration config is null");
272         return;
273     }
274     if (formRenderer_ == nullptr) {
275         HILOG_ERROR("UpdateConfiguration failed, formRenderer is null");
276         return;
277     }
278     formRenderer_->UpdateConfiguration(config);
279 }
280 
RecycleForm(std::string & statusData) const281 void FormRendererGroup::RecycleForm(std::string& statusData) const
282 {
283     if (formRenderer_ == nullptr) {
284         HILOG_ERROR("RecycleForm failed, formRenderer is null");
285         return;
286     }
287     formRenderer_->RecycleForm(statusData);
288 }
289 
RecoverRenderer(const std::vector<FormRequest> & formRequests,size_t currentCompIndex)290 void FormRendererGroup::RecoverRenderer(const std::vector<FormRequest>& formRequests, size_t currentCompIndex)
291 {
292     if (currentCompIndex >= formRequests.size()) {
293         HILOG_ERROR("current comp index %{public}zu invalid", currentCompIndex);
294         return;
295     }
296 
297     const FormRequest &currentComp = formRequests[currentCompIndex];
298     for (auto formRequest: formRequests) {
299         formRequests_.emplace_back(formRequest);
300     }
301     currentCompId_ = currentComp.compId;
302 
303     bool isVerified = currentComp.want.GetBoolParam(FORM_RENDER_STATE, false);
304     if (isVerified) {
305         HILOG_DEBUG("user verified, start recover renderer");
306         InnerAddForm(currentComp);
307         return;
308     }
309     HILOG_INFO("user not verified, delay recover renderer");
310     PreInitAddForm(currentComp);
311 }
312 }  // namespace Ace
313 }  // namespace OHOS
314