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
260 InitAddFormAcquireCallback(instanceID);
261 InitAddFormUpdateCallback(instanceID);
262 InitAddFormErrorCallback(instanceID);
263 InitAddFormUninstallCallback(instanceID);
264 }
265 }
266
OnActionEvent(const std::string & action) const267 void FormElement::OnActionEvent(const std::string& action) const
268 {
269 LOGI("begin action event");
270 auto eventAction = JsonUtil::ParseJsonString(action);
271 if (!eventAction->IsValid()) {
272 LOGE("get event action failed");
273 return;
274 }
275 auto actionType = eventAction->GetValue("action");
276 if (!actionType->IsValid()) {
277 LOGE("get event key failed");
278 return;
279 }
280
281 auto type = actionType->GetString();
282 if (type != "router" && type != "message") {
283 LOGE("undefined event type");
284 return;
285 }
286
287 #ifndef OHOS_STANDARD_SYSTEM
288 if ("router" == type) {
289 HandleOnRouterEvent(eventAction);
290 return;
291 }
292 #endif
293
294 if (formManagerBridge_) {
295 LOGI("send action event to ability.");
296 formManagerBridge_->OnActionEvent(action);
297 }
298 }
299
CreateCardContainer()300 void FormElement::CreateCardContainer()
301 {
302 if (subContainer_) {
303 auto id = subContainer_->GetRunningCardId();
304 FormManager::GetInstance().RemoveSubContainer(id);
305
306 subContainer_->Destroy();
307 subContainer_.Reset();
308 }
309
310 auto context = GetContext().Upgrade();
311 if (!context) {
312 LOGE("get context fail.");
313 return;
314 }
315 subContainer_ = AceType::MakeRefPtr<SubContainer>(context, context->GetInstanceId());
316 if (!subContainer_) {
317 LOGE("create card container fail.");
318 return;
319 }
320 subContainer_->Initialize();
321 subContainer_->SetFormComponent(component_);
322 auto form = AceType::DynamicCast<FormComponent>(component_);
323 if (!form) {
324 LOGE("form component is null when try adding nonmatched container to form manager.");
325 return;
326 }
327
328 auto formNode = AceType::DynamicCast<RenderForm>(renderNode_);
329 if (!formNode) {
330 LOGE("form node is null.");
331 return;
332 }
333 formNode->SetSubContainer(subContainer_);
334
335 subContainer_->AddFormAcquireCallback([weak = WeakClaim(this)](int64_t id) {
336 auto element = weak.Upgrade();
337 auto uiTaskExecutor =
338 SingleTaskExecutor::Make(element->GetContext().Upgrade()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
339 uiTaskExecutor.PostTask([id, weak] {
340 auto form = weak.Upgrade();
341 if (form) {
342 LOGI("card id:%{public}" PRId64, id);
343 form->HandleOnAcquireEvent(id);
344 }
345 }, "ArkUIFormAcquire");
346 });
347 }
348
CreateRenderNode()349 RefPtr<RenderNode> FormElement::CreateRenderNode()
350 {
351 return RenderForm::Create();
352 }
353
InitAddFormAcquireCallback(int32_t instanceID)354 void FormElement::InitAddFormAcquireCallback(int32_t instanceID)
355 {
356 auto callback = [weak = WeakClaim(this), instanceID](int64_t id, std::string path, std::string module,
357 std::string data, std::map<std::string, sptr<AppExecFwk::FormAshmem>> imageDataMap,
358 AppExecFwk::FormJsInfo formJsInfo, const FrontendType& frontendType,
359 const FrontendType& uiSyntax) {
360 ContainerScope scope(instanceID);
361 auto element = weak.Upgrade();
362 auto uiTaskExecutor =
363 SingleTaskExecutor::Make(element->GetContext().Upgrade()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
364 uiTaskExecutor.PostTask(
365 [id, path, module, data, imageDataMap, formJsInfo, weak, instanceID, frontendType, uiSyntax] {
366 ContainerScope scope(instanceID);
367 auto form = weak.Upgrade();
368 if (form && form->GetSubContainer()) {
369 auto container = form->GetSubContainer();
370 container->SetWindowConfig(
371 { formJsInfo.formWindow.designWidth, formJsInfo.formWindow.autoDesignWidth });
372 container->RunCard(
373 id, path, module, data, imageDataMap, formJsInfo.formSrc, frontendType, uiSyntax);
374 }
375 },
376 "ArkUIFormAcquireAndRunCard");
377 };
378 formManagerBridge_->AddFormAcquireCallback(callback);
379 }
380
InitAddFormUpdateCallback(int32_t instanceID)381 void FormElement::InitAddFormUpdateCallback(int32_t instanceID)
382 {
383 auto callback = [weak = WeakClaim(this), instanceID](int64_t id, std::string data,
384 std::map<std::string, sptr<AppExecFwk::FormAshmem>> imageDataMap) {
385 ContainerScope scope(instanceID);
386 auto element = weak.Upgrade();
387 auto uiTaskExecutor =
388 SingleTaskExecutor::Make(element->GetContext().Upgrade()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
389 uiTaskExecutor.PostTask(
390 [id, data, imageDataMap, weak, instanceID] {
391 ContainerScope scope(instanceID);
392 auto form = weak.Upgrade();
393 if (form && form->ISAllowUpdate()) {
394 form->GetSubContainer()->UpdateCard(data, imageDataMap);
395 }
396 },
397 "ArkUIFormUpdateCard");
398 };
399 formManagerBridge_->AddFormUpdateCallback(callback);
400 }
401
InitAddFormErrorCallback(int32_t instanceID)402 void FormElement::InitAddFormErrorCallback(int32_t instanceID)
403 {
404 formManagerBridge_->AddFormErrorCallback([weak = WeakClaim(this), instanceID](std::string code, std::string msg) {
405 ContainerScope scope(instanceID);
406 auto element = weak.Upgrade();
407 auto uiTaskExecutor =
408 SingleTaskExecutor::Make(element->GetContext().Upgrade()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
409 uiTaskExecutor.PostTask(
410 [code, msg, weak, instanceID] {
411 ContainerScope scope(instanceID);
412 auto form = weak.Upgrade();
413 if (form) {
414 form->HandleOnErrorEvent(code, msg);
415 }
416
417 auto render = form->GetRenderNode();
418 if (!render) {
419 LOGE("remove card from screen fail, due to could not get card render node");
420 return;
421 }
422 auto renderForm = AceType::DynamicCast<RenderForm>(render);
423 if (renderForm) {
424 renderForm->RemoveChildren();
425 }
426 },
427 "ArkUIFormRemoveCard");
428 });
429 }
430
InitAddFormUninstallCallback(int32_t instanceID)431 void FormElement::InitAddFormUninstallCallback(int32_t instanceID)
432 {
433 formManagerBridge_->AddFormUninstallCallback([weak = WeakClaim(this), instanceID](int64_t formId) {
434 ContainerScope scope(instanceID);
435 auto element = weak.Upgrade();
436 auto uiTaskExecutor =
437 SingleTaskExecutor::Make(element->GetContext().Upgrade()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
438 uiTaskExecutor.PostTask(
439 [formId, weak, instanceID] {
440 ContainerScope scope(instanceID);
441 auto form = weak.Upgrade();
442 if (form) {
443 form->HandleOnUninstallEvent(formId);
444 }
445 },
446 "ArkUIFormUninstall");
447 });
448 }
449
450 } // namespace OHOS::Ace
451