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 "core/components/form/form_element.h"
17
18 #include "core/common/container_scope.h"
19 #include "core/common/form_manager.h"
20 #ifdef OHOS_STANDARD_SYSTEM
21 #include "form_info.h"
22 #endif
23 #include "frameworks/base/utils/string_utils.h"
24 #include "frameworks/core/components/form/form_component.h"
25 #include "frameworks/core/components/form/render_form.h"
26 #include "frameworks/core/components/form/resource/form_manager_delegate.h"
27
28 namespace OHOS::Ace {
29
~FormElement()30 FormElement::~FormElement()
31 {
32 formManagerBridge_.Reset();
33
34 auto id = subContainer_->GetRunningCardId();
35 FormManager::GetInstance().RemoveSubContainer(id);
36
37 subContainer_->Destroy();
38 subContainer_.Reset();
39 }
40
Update()41 void FormElement::Update()
42 {
43 auto form = AceType::DynamicCast<FormComponent>(component_);
44 if (!form) {
45 LOGE("could not get form component for update");
46 return;
47 }
48 SetElementId(form->GetElementId());
49
50 auto info = form->GetFormRequestInfo();
51 if (info.bundleName != cardInfo_.bundleName || info.abilityName != cardInfo_.abilityName ||
52 info.moduleName != cardInfo_.moduleName || info.cardName != cardInfo_.cardName ||
53 info.dimension != cardInfo_.dimension) {
54 cardInfo_ = info;
55 } else {
56 // for update form component
57 UpdateInner(info);
58 return;
59 }
60
61 GetRenderNode()->Update(component_);
62
63 #if OHOS_STANDARD_SYSTEM
64 AppExecFwk::FormInfo formInfo;
65 if (!FormManagerDelegate::GetFormInfo(info.bundleName, info.moduleName, info.cardName, formInfo)) {
66 LOGE("failed to get formInfo with bundleName: %{public}s, moduleName: %{public}s, cardName: %{public}s",
67 info.bundleName.c_str(), info.moduleName.c_str(), info.cardName.c_str());
68 }
69 #endif
70
71 CreateCardContainer();
72
73 if (formManagerBridge_) {
74 #if OHOS_STANDARD_SYSTEM
75 formManagerBridge_->AddForm(GetContext(), info, formInfo);
76 #else
77 formManagerBridge_->AddForm(GetContext(), info);
78 #endif
79 }
80
81 InitEvent(form);
82 }
83
PerformBuild()84 void FormElement::PerformBuild()
85 {
86 subContainer_->SetFormElement(AceType::WeakClaim(this));
87 }
88
InitEvent(const RefPtr<FormComponent> & component)89 void FormElement::InitEvent(const RefPtr<FormComponent>& component)
90 {
91 if (!component->GetOnAcquireFormEventId().IsEmpty()) {
92 onAcquireEvent_ =
93 AceAsyncEvent<void(const std::string&)>::Create(component->GetOnAcquireFormEventId(), context_);
94 }
95
96 if (!component->GetOnErrorEvent().IsEmpty()) {
97 onErrorEvent_ = AceAsyncEvent<void(const std::string&)>::Create(component->GetOnErrorEvent(), context_);
98 }
99
100 if (!component->GetOnUninstallEvent().IsEmpty()) {
101 onUninstallEvent_ =
102 AceAsyncEvent<void(const std::string&)>::Create(component->GetOnUninstallEvent(), context_);
103 }
104
105 if (!component->GetOnRouterEvent().IsEmpty()) {
106 onRouterEvent_ = AceAsyncEvent<void(const std::string&)>::Create(component->GetOnRouterEvent(), context_);
107 }
108 }
109
UpdateInner(const RequestFormInfo & info)110 void FormElement::UpdateInner(const RequestFormInfo& info)
111 {
112 if (cardInfo_.allowUpdate != info.allowUpdate) {
113 cardInfo_.allowUpdate = info.allowUpdate;
114 LOGI(" update card allow info:%{public}d", cardInfo_.allowUpdate);
115 if (subContainer_) {
116 subContainer_->SetAllowUpdate(cardInfo_.allowUpdate);
117 }
118 }
119
120 if (cardInfo_.width != info.width || cardInfo_.height != info.height) {
121 LOGI("update card size old w:%lf,h:%lf", cardInfo_.width.Value(), cardInfo_.height.Value());
122 LOGI("update card size new w:%lf,h:%lf", info.width.Value(), info.height.Value());
123 cardInfo_.width = info.width;
124 cardInfo_.height = info.height;
125 GetRenderNode()->Update(component_);
126 subContainer_->SetFormComponent(component_);
127 subContainer_->UpdateRootElementSize();
128 subContainer_->UpdateSurfaceSize();
129 }
130 }
131
HandleOnAcquireEvent(int64_t id)132 void FormElement::HandleOnAcquireEvent(int64_t id)
133 {
134 if (!onAcquireEvent_) {
135 LOGE("could not find available event handle");
136 return;
137 }
138 auto context = context_.Upgrade();
139 if (!context) {
140 LOGE("fail to get context, onAcquire failed.");
141 return;
142 }
143
144 auto json = JsonUtil::Create(true);
145 json->Put("id", std::to_string(id).c_str());
146 LOGI("HandleOnAcquireEvent msg:%{public}s", json->ToString().c_str());
147 int32_t instance = context->GetInstanceId();
148 context->GetTaskExecutor()->PostTask(
149 [weak = WeakClaim(this), info = json->ToString(), instance] {
150 auto element = weak.Upgrade();
151 if (element != nullptr && element->onAcquireEvent_ != nullptr) {
152 ContainerScope scope(instance);
153 element->onAcquireEvent_(info);
154 }
155 },
156 TaskExecutor::TaskType::JS, "ArkUIFormHandleOnAcquireEvent");
157 }
158
HandleOnRouterEvent(const std::unique_ptr<JsonValue> & action)159 void FormElement::HandleOnRouterEvent(const std::unique_ptr<JsonValue>& action)
160 {
161 if (!onRouterEvent_) {
162 LOGE("action could not find available event handle");
163 return;
164 }
165 auto context = context_.Upgrade();
166 if (!context) {
167 LOGE("fail to get context, onRouter failed.");
168 return;
169 }
170
171 auto json = JsonUtil::Create(true);
172 json->Put("action", action);
173
174 LOGI("HandleOnRouterEvent msg:%{public}s", json->ToString().c_str());
175 int32_t instance = context->GetInstanceId();
176 context->GetTaskExecutor()->PostTask(
177 [weak = WeakClaim(this), info = json->ToString(), instance] {
178 auto element = weak.Upgrade();
179 if (element != nullptr && element->onRouterEvent_ != nullptr) {
180 ContainerScope scope(instance);
181 element->onRouterEvent_(info);
182 }
183 },
184 TaskExecutor::TaskType::JS, "ArkUIFormHandleOnRouterEvent");
185 }
186
HandleOnErrorEvent(const std::string code,const std::string msg)187 void FormElement::HandleOnErrorEvent(const std::string code, const std::string msg)
188 {
189 if (!onErrorEvent_) {
190 LOGE("could not find available event handle");
191 return;
192 }
193 auto context = context_.Upgrade();
194 if (!context) {
195 LOGE("fail to get context, onError failed.");
196 return;
197 }
198
199 auto json = JsonUtil::Create(true);
200 json->Put("errcode", code.c_str());
201 json->Put("msg", msg.c_str());
202
203 LOGI("HandleOnErrorEvent msg:%{public}s", msg.c_str());
204 int32_t instance = context->GetInstanceId();
205 context->GetTaskExecutor()->PostTask(
206 [weak = WeakClaim(this), info = json->ToString(), instance] {
207 auto element = weak.Upgrade();
208 if (element != nullptr && element->onErrorEvent_ != nullptr) {
209 ContainerScope scope(instance);
210 element->onErrorEvent_(info);
211 }
212 },
213 TaskExecutor::TaskType::JS, "ArkUIFormHandleOnErrorEvent");
214 }
215
HandleOnUninstallEvent(int64_t formId)216 void FormElement::HandleOnUninstallEvent(int64_t formId)
217 {
218 if (!onUninstallEvent_) {
219 LOGE("could not find available event handle");
220 return;
221 }
222 auto context = context_.Upgrade();
223 if (!context) {
224 LOGE("fail to get context, onUninstall failed.");
225 return;
226 }
227
228 auto json = JsonUtil::Create(true);
229 json->Put("id", std::to_string(formId).c_str());
230 LOGI("HandleOnUninstallEvent formId:%{public}s", std::to_string(formId).c_str());
231 int32_t instance = context->GetInstanceId();
232 context->GetTaskExecutor()->PostTask(
233 [weak = WeakClaim(this), info = json->ToString(), instance] {
234 auto element = weak.Upgrade();
235 if (element != nullptr && element->onUninstallEvent_ != nullptr) {
236 ContainerScope scope(instance);
237 element->onUninstallEvent_(info);
238 }
239 },
240 TaskExecutor::TaskType::JS, "ArkUIFormHandleOnUninstallEvent");
241 }
242
Prepare(const WeakPtr<Element> & parent)243 void FormElement::Prepare(const WeakPtr<Element>& parent)
244 {
245 RenderElement::Prepare(parent);
246 auto context = context_.Upgrade();
247 if (!context) {
248 LOGE("fail to get context, onUninstall failed.");
249 return;
250 }
251
252 if (!formManagerBridge_) {
253 formManagerBridge_ = AceType::MakeRefPtr<FormManagerDelegate>(GetContext());
254 int32_t instanceID = context->GetInstanceId();
255 auto formUtils = FormManager::GetInstance().GetFormUtils();
256 if (formUtils) {
257 formManagerBridge_->SetFormUtils(formUtils);
258 }
259 formManagerBridge_->AddFormAcquireCallback(
260 [weak = WeakClaim(this), instanceID](int64_t id, std::string path, std::string module, std::string data,
261 std::map<std::string, sptr<AppExecFwk::FormAshmem>> imageDataMap, AppExecFwk::FormJsInfo formJsInfo,
262 const FrontendType& frontendType, const FrontendType& uiSyntax) {
263 ContainerScope scope(instanceID);
264 auto element = weak.Upgrade();
265 auto uiTaskExecutor = SingleTaskExecutor::Make(
266 element->GetContext().Upgrade()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
267 uiTaskExecutor.PostTask([id, path, module, data, imageDataMap, formJsInfo, weak,
268 instanceID, frontendType, uiSyntax] {
269 ContainerScope scope(instanceID);
270 auto form = weak.Upgrade();
271 if (form) {
272 auto container = form->GetSubContainer();
273 if (container) {
274 container->SetWindowConfig(
275 { formJsInfo.formWindow.designWidth, formJsInfo.formWindow.autoDesignWidth });
276 container->RunCard(id, path, module, data, imageDataMap,
277 formJsInfo.formSrc, frontendType, uiSyntax);
278 }
279 }
280 }, "ArkUIFormAcquireAndRunCard");
281 });
282 formManagerBridge_->AddFormUpdateCallback([weak = WeakClaim(this), instanceID](int64_t id, std::string data,
283 std::map<std::string, sptr<AppExecFwk::FormAshmem>> imageDataMap) {
284 ContainerScope scope(instanceID);
285 auto element = weak.Upgrade();
286 auto uiTaskExecutor = SingleTaskExecutor::Make(
287 element->GetContext().Upgrade()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
288 uiTaskExecutor.PostTask([id, data, imageDataMap, weak, instanceID] {
289 ContainerScope scope(instanceID);
290 auto form = weak.Upgrade();
291 if (form) {
292 if (form->ISAllowUpdate()) {
293 form->GetSubContainer()->UpdateCard(data, imageDataMap);
294 }
295 }
296 }, "ArkUIFormUpdateCard");
297 });
298 formManagerBridge_->AddFormErrorCallback(
299 [weak = WeakClaim(this), instanceID](std::string code, std::string msg) {
300 ContainerScope scope(instanceID);
301 auto element = weak.Upgrade();
302 auto uiTaskExecutor = SingleTaskExecutor::Make(
303 element->GetContext().Upgrade()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
304 uiTaskExecutor.PostTask([code, msg, weak, instanceID] {
305 ContainerScope scope(instanceID);
306 auto form = weak.Upgrade();
307 if (form) {
308 form->HandleOnErrorEvent(code, msg);
309 }
310
311 auto render = form->GetRenderNode();
312 if (!render) {
313 LOGE("remove card from screen fail, due to could not get card render node");
314 return;
315 }
316 auto renderForm = AceType::DynamicCast<RenderForm>(render);
317 if (renderForm) {
318 renderForm->RemoveChildren();
319 }
320 }, "ArkUIFormRemoveCard");
321 });
322 formManagerBridge_->AddFormUninstallCallback(
323 [weak = WeakClaim(this), instanceID](int64_t formId) {
324 ContainerScope scope(instanceID);
325 auto element = weak.Upgrade();
326 auto uiTaskExecutor = SingleTaskExecutor::Make(
327 element->GetContext().Upgrade()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
328 uiTaskExecutor.PostTask(
329 [formId, weak, instanceID] {
330 ContainerScope scope(instanceID);
331 auto form = weak.Upgrade();
332 if (form) {
333 form->HandleOnUninstallEvent(formId);
334 }
335 }, "ArkUIFormUninstall");
336 });
337 }
338 }
339
OnActionEvent(const std::string & action) const340 void FormElement::OnActionEvent(const std::string& action) const
341 {
342 LOGI("begin action event");
343 auto eventAction = JsonUtil::ParseJsonString(action);
344 if (!eventAction->IsValid()) {
345 LOGE("get event action failed");
346 return;
347 }
348 auto actionType = eventAction->GetValue("action");
349 if (!actionType->IsValid()) {
350 LOGE("get event key failed");
351 return;
352 }
353
354 auto type = actionType->GetString();
355 if (type != "router" && type != "message") {
356 LOGE("undefined event type");
357 return;
358 }
359
360 #ifndef OHOS_STANDARD_SYSTEM
361 if ("router" == type) {
362 HandleOnRouterEvent(eventAction);
363 return;
364 }
365 #endif
366
367 if (formManagerBridge_) {
368 LOGI("send action event to ability.");
369 formManagerBridge_->OnActionEvent(action);
370 }
371 }
372
CreateCardContainer()373 void FormElement::CreateCardContainer()
374 {
375 if (subContainer_) {
376 auto id = subContainer_->GetRunningCardId();
377 FormManager::GetInstance().RemoveSubContainer(id);
378
379 subContainer_->Destroy();
380 subContainer_.Reset();
381 }
382
383 auto context = GetContext().Upgrade();
384 if (!context) {
385 LOGE("get context fail.");
386 return;
387 }
388 subContainer_ = AceType::MakeRefPtr<SubContainer>(context, context->GetInstanceId());
389 if (!subContainer_) {
390 LOGE("create card container fail.");
391 return;
392 }
393 subContainer_->Initialize();
394 subContainer_->SetFormComponent(component_);
395 auto form = AceType::DynamicCast<FormComponent>(component_);
396 if (!form) {
397 LOGE("form component is null when try adding nonmatched container to form manager.");
398 return;
399 }
400
401 auto formNode = AceType::DynamicCast<RenderForm>(renderNode_);
402 if (!formNode) {
403 LOGE("form node is null.");
404 return;
405 }
406 formNode->SetSubContainer(subContainer_);
407
408 subContainer_->AddFormAcquireCallback([weak = WeakClaim(this)](int64_t id) {
409 auto element = weak.Upgrade();
410 auto uiTaskExecutor =
411 SingleTaskExecutor::Make(element->GetContext().Upgrade()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
412 uiTaskExecutor.PostTask([id, weak] {
413 auto form = weak.Upgrade();
414 if (form) {
415 LOGI("card id:%{public}" PRId64, id);
416 form->HandleOnAcquireEvent(id);
417 }
418 }, "ArkUIFormAcquire");
419 });
420 }
421
CreateRenderNode()422 RefPtr<RenderNode> FormElement::CreateRenderNode()
423 {
424 return RenderForm::Create();
425 }
426
427 } // namespace OHOS::Ace
428