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.h"
17
18 #include "configuration.h"
19 #include "form_constants.h"
20 #include "form_renderer_hilog.h"
21 #include "event_handler.h"
22 #include "refbase.h"
23
24 #include "base/utils/utils.h"
25
26 namespace OHOS {
27 namespace Ace {
28 namespace {
29 constexpr char FORM_RENDERER_ALLOW_UPDATE[] = "allowUpdate";
30 constexpr char FORM_RENDERER_DISPATCHER[] = "ohos.extra.param.key.process_on_form_renderer_dispatcher";
31 constexpr char FORM_RENDERER_PROCESS_ON_ADD_SURFACE[] = "ohos.extra.param.key.process_on_add_surface";
32 } // namespace
33
34 using EventHandler = OHOS::AppExecFwk::EventHandler;
35
FormRenderer(const std::shared_ptr<OHOS::AbilityRuntime::Context> context,const std::shared_ptr<OHOS::AbilityRuntime::Runtime> runtime)36 FormRenderer::FormRenderer(const std::shared_ptr<OHOS::AbilityRuntime::Context> context,
37 const std::shared_ptr<OHOS::AbilityRuntime::Runtime> runtime)
38 : context_(context), runtime_(runtime)
39 {
40 HILOG_INFO("FormRenderer %{public}p created.", this);
41 if (!context_ || !runtime_) {
42 return;
43 }
44 auto& nativeEngine = (static_cast<AbilityRuntime::JsRuntime&>(*runtime_.get())).GetNativeEngine();
45 uiContent_ = UIContent::Create(context_.get(), &nativeEngine, true);
46 }
47
InitUIContent(const OHOS::AppExecFwk::FormJsInfo & formJsInfo)48 void FormRenderer::InitUIContent(const OHOS::AppExecFwk::FormJsInfo& formJsInfo)
49 {
50 HILOG_INFO("InitUIContent width = %{public}f , height = %{public}f.", width_, height_);
51 SetAllowUpdate(allowUpdate_);
52 uiContent_->SetFormWidth(width_);
53 uiContent_->SetFormHeight(height_);
54 uiContent_->UpdateFormSharedImage(formJsInfo.imageDataMap);
55 uiContent_->UpdateFormData(formJsInfo.formData);
56 uiContent_->Initialize(nullptr, formJsInfo.formSrc, nullptr);
57
58 auto actionEventHandler = [weak = weak_from_this()](const std::string& action) {
59 auto formRenderer = weak.lock();
60 if (formRenderer) {
61 formRenderer->OnActionEvent(action);
62 }
63 };
64 uiContent_->SetActionEventHandler(actionEventHandler);
65
66 auto errorEventHandler = [weak = weak_from_this()](const std::string& code, const std::string& msg) {
67 auto formRenderer = weak.lock();
68 if (formRenderer) {
69 formRenderer->OnError(code, msg);
70 }
71 };
72 uiContent_->SetErrorEventHandler(errorEventHandler);
73
74 if (!formJsInfo.isDynamic) {
75 auto formLinkInfoUpdateHandler = [weak = weak_from_this()](const std::vector<std::string>& formLinkInfos) {
76 auto formRenderer = weak.lock();
77 if (formRenderer) {
78 formRenderer->OnFormLinkInfoUpdate(formLinkInfos);
79 }
80 };
81 uiContent_->SetFormLinkInfoUpdateHandler(formLinkInfoUpdateHandler);
82 }
83
84 auto rsSurfaceNode = uiContent_->GetFormRootNode();
85 if (rsSurfaceNode == nullptr) {
86 return;
87 }
88 rsSurfaceNode->SetBounds(0.0f, 0.0f, width_, height_);
89 uiContent_->Foreground();
90 }
91
ParseWant(const OHOS::AAFwk::Want & want)92 void FormRenderer::ParseWant(const OHOS::AAFwk::Want& want)
93 {
94 allowUpdate_ = want.GetBoolParam(FORM_RENDERER_ALLOW_UPDATE, true);
95 width_ = want.GetDoubleParam(OHOS::AppExecFwk::Constants::PARAM_FORM_WIDTH_KEY, 0.0f);
96 height_ = want.GetDoubleParam(OHOS::AppExecFwk::Constants::PARAM_FORM_HEIGHT_KEY, 0.0f);
97 proxy_ = want.GetRemoteObject(FORM_RENDERER_PROCESS_ON_ADD_SURFACE);
98 }
99
AddForm(const OHOS::AAFwk::Want & want,const OHOS::AppExecFwk::FormJsInfo & formJsInfo)100 void FormRenderer::AddForm(const OHOS::AAFwk::Want& want, const OHOS::AppExecFwk::FormJsInfo& formJsInfo)
101 {
102 if (uiContent_ == nullptr) {
103 HILOG_ERROR("uiContent is null!");
104 return;
105 }
106 formRendererDispatcherImpl_ = new FormRendererDispatcherImpl(uiContent_, shared_from_this());
107 ParseWant(want);
108 InitUIContent(formJsInfo);
109 SetRenderDelegate(proxy_);
110 OnSurfaceCreate(formJsInfo);
111 }
112
ReloadForm(const std::string & url)113 void FormRenderer::ReloadForm(const std::string& url)
114 {
115 if (!uiContent_) {
116 HILOG_ERROR("uiContent_ is null");
117 return;
118 }
119 uiContent_->ReloadForm(url);
120 }
121
IsAllowUpdate()122 bool FormRenderer::IsAllowUpdate()
123 {
124 if (formRendererDispatcherImpl_ == nullptr) {
125 HILOG_ERROR("formRendererDispatcherImpl is null");
126 return true;
127 }
128
129 return formRendererDispatcherImpl_->IsAllowUpdate();
130 }
131
SetAllowUpdate(bool allowUpdate)132 void FormRenderer::SetAllowUpdate(bool allowUpdate)
133 {
134 if (formRendererDispatcherImpl_ == nullptr) {
135 HILOG_ERROR("formRendererDispatcherImpl is null");
136 return;
137 }
138
139 formRendererDispatcherImpl_->SetAllowUpdate(allowUpdate);
140 }
141
UpdateForm(const OHOS::AppExecFwk::FormJsInfo & formJsInfo)142 void FormRenderer::UpdateForm(const OHOS::AppExecFwk::FormJsInfo& formJsInfo)
143 {
144 if (!IsAllowUpdate()) {
145 HILOG_ERROR("Not allow update");
146 return;
147 }
148 if (!uiContent_) {
149 HILOG_ERROR("uiContent_ is null");
150 return;
151 }
152 uiContent_->UpdateFormSharedImage(formJsInfo.imageDataMap);
153 uiContent_->UpdateFormData(formJsInfo.formData);
154 }
155
Destroy()156 void FormRenderer::Destroy()
157 {
158 HILOG_INFO("Destroy FormRenderer start.");
159 if (formRendererDelegate_ != nullptr) {
160 auto rsSurfaceNode = uiContent_->GetFormRootNode();
161 if (rsSurfaceNode != nullptr) {
162 HILOG_INFO("Form OnSurfaceRelease!");
163 formRendererDelegate_->OnSurfaceRelease(rsSurfaceNode->GetId());
164 }
165 }
166
167 if (formRendererDelegate_ != nullptr && formRendererDelegate_->AsObject() != nullptr) {
168 formRendererDelegate_->AsObject()->RemoveDeathRecipient(renderDelegateDeathRecipient_);
169 }
170 renderDelegateDeathRecipient_ = nullptr;
171 formRendererDelegate_ = nullptr;
172 formRendererDispatcherImpl_ = nullptr;
173 if (uiContent_) {
174 uiContent_->Destroy();
175 uiContent_ = nullptr;
176 }
177 context_ = nullptr;
178 runtime_ = nullptr;
179 HILOG_INFO("Destroy FormRenderer finish.");
180 }
181
OnSurfaceChange(float width,float height)182 void FormRenderer::OnSurfaceChange(float width, float height)
183 {
184 if (!formRendererDelegate_) {
185 HILOG_ERROR("form renderer delegate is null!");
186 return;
187 }
188 formRendererDelegate_->OnSurfaceChange(width, height);
189 }
190
OnSurfaceCreate(const OHOS::AppExecFwk::FormJsInfo & formJsInfo)191 void FormRenderer::OnSurfaceCreate(const OHOS::AppExecFwk::FormJsInfo& formJsInfo)
192 {
193 if (!formRendererDispatcherImpl_) {
194 HILOG_ERROR("form renderer dispatcher is null!");
195 return;
196 }
197 if (!formRendererDelegate_) {
198 HILOG_ERROR("form renderer delegate is null!");
199 return;
200 }
201 OHOS::AAFwk::Want newWant;
202 newWant.SetParam(FORM_RENDERER_DISPATCHER, formRendererDispatcherImpl_->AsObject());
203 auto rsSurfaceNode = uiContent_->GetFormRootNode();
204 HILOG_INFO("Form OnSurfaceCreate!");
205 formRendererDelegate_->OnSurfaceCreate(rsSurfaceNode, formJsInfo, newWant);
206 }
207
OnSurfaceReuse(const OHOS::AppExecFwk::FormJsInfo & formJsInfo)208 void FormRenderer::OnSurfaceReuse(const OHOS::AppExecFwk::FormJsInfo& formJsInfo)
209 {
210 if (!formRendererDispatcherImpl_) {
211 HILOG_ERROR("form renderer dispatcher is null!");
212 return;
213 }
214 if (!formRendererDelegate_) {
215 HILOG_ERROR("form renderer delegate is null!");
216 return;
217 }
218 auto rsSurfaceNode = uiContent_->GetFormRootNode();
219 if (rsSurfaceNode == nullptr) {
220 HILOG_ERROR("form renderer rsSurfaceNode is null!");
221 return;
222 }
223 OHOS::AAFwk::Want newWant;
224 newWant.SetParam(FORM_RENDERER_DISPATCHER, formRendererDispatcherImpl_->AsObject());
225 HILOG_INFO("Form OnSurfaceReuse.");
226 formRendererDelegate_->OnSurfaceReuse(rsSurfaceNode->GetId(), formJsInfo, newWant);
227 formRendererDelegate_->OnFormLinkInfoUpdate(cachedInfos_);
228 }
229
OnActionEvent(const std::string & action)230 void FormRenderer::OnActionEvent(const std::string& action)
231 {
232 if (!formRendererDelegate_) {
233 HILOG_ERROR("formRendererDelegate is null!");
234 return;
235 }
236
237 formRendererDelegate_->OnActionEvent(action);
238 }
239
OnError(const std::string & code,const std::string & msg)240 void FormRenderer::OnError(const std::string& code, const std::string& msg)
241 {
242 if (!formRendererDelegate_) {
243 HILOG_ERROR("formRendererDelegate is null!");
244 return;
245 }
246
247 formRendererDelegate_->OnError(code, msg);
248 }
249
OnFormLinkInfoUpdate(const std::vector<std::string> & formLinkInfos)250 void FormRenderer::OnFormLinkInfoUpdate(const std::vector<std::string>& formLinkInfos)
251 {
252 if (!formRendererDelegate_) {
253 HILOG_ERROR("formRendererDelegate is null!");
254 return;
255 }
256 cachedInfos_ = formLinkInfos;
257 formRendererDelegate_->OnFormLinkInfoUpdate(formLinkInfos);
258 }
259
SetRenderDelegate(const sptr<IRemoteObject> & remoteObj)260 void FormRenderer::SetRenderDelegate(const sptr<IRemoteObject>& remoteObj)
261 {
262 HILOG_INFO("Get renderRemoteObj, add death recipient.");
263 auto renderRemoteObj = iface_cast<IFormRendererDelegate>(remoteObj);
264 if (renderRemoteObj == nullptr) {
265 HILOG_ERROR("renderRemoteObj is nullptr.");
266 return;
267 }
268
269 formRendererDelegate_ = renderRemoteObj;
270
271 if (renderDelegateDeathRecipient_ == nullptr) {
272 renderDelegateDeathRecipient_ = new FormRenderDelegateRecipient(
273 [eventHandler = std::weak_ptr<EventHandler>(EventHandler::Current()), renderer = weak_from_this()]() {
274 auto handler = eventHandler.lock();
275 if (!handler) {
276 HILOG_ERROR("eventHandler is nullptr");
277 return;
278 }
279
280 handler->PostTask([weak = renderer]() {
281 auto formRender = weak.lock();
282 if (!formRender) {
283 HILOG_ERROR("formRender is nullptr");
284 return;
285 }
286 formRender->ResetRenderDelegate();
287 });
288 });
289 }
290 auto renderDelegate = formRendererDelegate_->AsObject();
291 if (renderDelegate == nullptr) {
292 HILOG_ERROR("renderDelegate is nullptr, can not get obj from renderRemoteObj.");
293 return;
294 }
295 renderDelegate->AddDeathRecipient(renderDelegateDeathRecipient_);
296 }
297
ResetRenderDelegate()298 void FormRenderer::ResetRenderDelegate()
299 {
300 HILOG_INFO("ResetRenderDelegate.");
301 formRendererDelegate_ = nullptr;
302 }
303
UpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)304 void FormRenderer::UpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
305 {
306 if (!uiContent_) {
307 HILOG_ERROR("uiContent_ is null");
308 return;
309 }
310
311 uiContent_->UpdateConfiguration(config);
312 }
313
OnRemoteDied(const wptr<IRemoteObject> & remote)314 void FormRenderDelegateRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
315 {
316 HILOG_ERROR("Recv FormRenderDelegate death notice");
317 if (remote == nullptr) {
318 HILOG_ERROR("weak remote is null");
319 return;
320 }
321 if (handler_) {
322 handler_();
323 }
324 }
325
AttachForm(const OHOS::AAFwk::Want & want,const OHOS::AppExecFwk::FormJsInfo & formJsInfo)326 void FormRenderer::AttachForm(const OHOS::AAFwk::Want& want, const OHOS::AppExecFwk::FormJsInfo& formJsInfo)
327 {
328 if (uiContent_ == nullptr) {
329 HILOG_ERROR("uiContent is null!");
330 return;
331 }
332 ParseWant(want);
333 AttachUIContent(formJsInfo);
334 SetRenderDelegate(proxy_);
335 OnSurfaceReuse(formJsInfo);
336 }
337
AttachUIContent(const OHOS::AppExecFwk::FormJsInfo & formJsInfo)338 void FormRenderer::AttachUIContent(const OHOS::AppExecFwk::FormJsInfo& formJsInfo)
339 {
340 HILOG_INFO("AttachUIContent width = %{public}f , height = %{public}f.", width_, height_);
341 SetAllowUpdate(allowUpdate_);
342 auto rsSurfaceNode = uiContent_->GetFormRootNode();
343 if (rsSurfaceNode == nullptr) {
344 HILOG_ERROR("rsSurfaceNode is nullptr.");
345 return;
346 }
347 if (!NearEqual(width_, uiContent_->GetFormWidth()) || !NearEqual(height_, uiContent_->GetFormHeight())) {
348 uiContent_->SetFormWidth(width_);
349 uiContent_->SetFormHeight(height_);
350 uiContent_->OnFormSurfaceChange(width_, height_);
351 rsSurfaceNode->SetBounds(0.0f, 0.0f, width_, height_);
352 }
353 uiContent_->Foreground();
354 }
355 } // namespace Ace
356 } // namespace OHOS
357