• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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