1 /*
2  * Copyright (c) 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 "frameworks/bridge/card_frontend/card_frontend_declarative.h"
17 
18 #include "frameworks/bridge/declarative_frontend/ng/page_router_manager_factory.h"
19 #include "frameworks/core/pipeline_ng/pipeline_context.h"
20 
21 namespace OHOS::Ace {
22 namespace {
23 
24 const char FILE_TYPE_BIN[] = ".abc";
25 
26 } // namespace
27 
~CardFrontendDeclarative()28 CardFrontendDeclarative::~CardFrontendDeclarative()
29 {
30     TAG_LOGI(AceLogTag::ACE_FORM, "CardDeclarative Destroyed");
31 }
32 
Initialize(FrontendType type, const RefPtr<TaskExecutor>& taskExecutor)33 bool CardFrontendDeclarative::Initialize(FrontendType type, const RefPtr<TaskExecutor>& taskExecutor)
34 {
35     type_ = type;
36     taskExecutor_ = taskExecutor;
37     InitializeDelegate(taskExecutor);
38     manifestParser_ = AceType::MakeRefPtr<Framework::ManifestParser>();
39     return true;
40 }
41 
InitializeDelegate(const RefPtr<TaskExecutor>& taskExecutor)42 void CardFrontendDeclarative::InitializeDelegate(const RefPtr<TaskExecutor>& taskExecutor)
43 {
44     auto pageRouterManager = NG::PageRouterManagerFactory::CreateManager();
45     delegate_ = AceType::MakeRefPtr<Framework::CardFrontendDelegateDeclarative>(taskExecutor);
46     delegate_->SetPageRouterManager(pageRouterManager);
47 }
48 
GetPageRouterManager() const49 RefPtr<NG::PageRouterManager> CardFrontendDeclarative::GetPageRouterManager() const
50 {
51     CHECK_NULL_RETURN(delegate_, nullptr);
52     return delegate_->GetPageRouterManager();
53 }
54 
Destroy()55 void CardFrontendDeclarative::Destroy()
56 {
57     CHECK_RUN_ON(JS);
58     delegate_.Reset();
59     eventHandler_.Reset();
60 }
61 
AttachPipelineContext(const RefPtr<PipelineBase>& context)62 void CardFrontendDeclarative::AttachPipelineContext(const RefPtr<PipelineBase>& context)
63 {
64     auto pipelineContext = DynamicCast<NG::PipelineContext>(context);
65     CHECK_NULL_VOID(delegate_);
66     CHECK_NULL_VOID(pipelineContext);
67     eventHandler_ = AceType::MakeRefPtr<CardEventHandlerDeclarative>(delegate_);
68 
69     holder_.Attach(context);
70     delegate_->AttachPipelineContext(context);
71 }
72 
SetAssetManager(const RefPtr<AssetManager>& assetManager)73 void CardFrontendDeclarative::SetAssetManager(const RefPtr<AssetManager>& assetManager)
74 {
75     assetManager_ = assetManager;
76     if (delegate_) {
77         delegate_->SetAssetManager(assetManager);
78     }
79 }
80 
RunPage(const std::string& url, const std::string& params)81 UIContentErrorCode CardFrontendDeclarative::RunPage(const std::string& url, const std::string& params)
82 {
83     std::string urlPath;
84     if (GetFormSrc().empty()) {
85         ParseManifest();
86         if (!url.empty()) {
87             urlPath = manifestParser_->GetRouter()->GetPagePath(url, FILE_TYPE_BIN);
88         }
89         if (urlPath.empty()) {
90             urlPath = manifestParser_->GetRouter()->GetEntry(FILE_TYPE_BIN);
91         }
92     } else {
93         urlPath = GetFormSrcPath(GetFormSrc(), FILE_TYPE_BIN);
94     }
95     if (urlPath.empty()) {
96         return UIContentErrorCode::NULL_URL;
97     }
98 
99     if (delegate_) {
100         auto container = Container::Current();
101         if (!container) {
102             return UIContentErrorCode::NULL_POINTER;
103         }
104         container->SetCardFrontend(AceType::WeakClaim(this), cardId_);
105         return delegate_->RunCard(urlPath, params, "", cardId_);
106     }
107 
108     return UIContentErrorCode::NULL_POINTER;
109 }
110 
OnPageLoaded(const RefPtr<Framework::JsAcePage>& page)111 void CardFrontendDeclarative::OnPageLoaded(const RefPtr<Framework::JsAcePage>& page)
112 {
113     CHECK_RUN_ON(JS);
114     // Pop all JS command and execute them in UI thread.
115     auto jsCommands = std::make_shared<std::vector<RefPtr<Framework::JsCommand>>>();
116     page->PopAllCommands(*jsCommands);
117     page->SetPipelineContext(holder_.Get());
118     taskExecutor_->PostTask(
119         [weak = AceType::WeakClaim(this), page, jsCommands] {
120             auto frontend = weak.Upgrade();
121             CHECK_NULL_VOID(frontend);
122             // Flush all JS commands.
123             for (const auto& command : *jsCommands) {
124                 command->Execute(page);
125             }
126 
127             auto pipelineContext = AceType::DynamicCast<PipelineContext>(frontend->holder_.Get());
128             CHECK_NULL_VOID(pipelineContext);
129             auto minSdk = frontend->manifestParser_->GetMinPlatformVersion();
130             pipelineContext->SetMinPlatformVersion(minSdk);
131 
132             auto document = page->GetDomDocument();
133             if (frontend->pageLoaded_) {
134                 page->ClearShowCommand();
135                 std::vector<NodeId> dirtyNodes;
136                 page->PopAllDirtyNodes(dirtyNodes);
137                 if (dirtyNodes.empty()) {
138                     return;
139                 }
140                 auto rootNodeId = dirtyNodes.front();
141                 if (rootNodeId == DOM_ROOT_NODE_ID_BASE) {
142                     auto patchComponent = page->BuildPagePatch(rootNodeId);
143                     if (patchComponent) {
144                         pipelineContext->ScheduleUpdate(patchComponent);
145                     }
146                 }
147                 if (document) {
148                     // When a component is configured with "position: fixed", there is a proxy node in root tree
149                     // instead of the real composed node. So here updates the real composed node.
150                     for (int32_t nodeId : document->GetProxyRelatedNodes()) {
151                         auto patchComponent = page->BuildPagePatch(nodeId);
152                         if (patchComponent) {
153                             pipelineContext->ScheduleUpdate(patchComponent);
154                         }
155                     }
156                 }
157                 return;
158             }
159 
160             // Just clear all dirty nodes.
161             page->ClearAllDirtyNodes();
162             if (document) {
163                 document->HandleComponentPostBinding();
164             }
165             if (pipelineContext->GetAccessibilityManager()) {
166                 pipelineContext->GetAccessibilityManager()->HandleComponentPostBinding();
167             }
168             if (pipelineContext->CanPushPage()) {
169                 pipelineContext->PushPage(page->BuildPage(page->GetUrl()));
170                 frontend->pageLoaded_ = true;
171             }
172         },
173         TaskExecutor::TaskType::UI, "ArkUICardFrontendPageLoaded");
174 }
175 
UpdateData(const std::string& dataList)176 void CardFrontendDeclarative::UpdateData(const std::string& dataList)
177 {
178     taskExecutor_->PostTask(
179         [weak = AceType::WeakClaim(this), dataList] {
180             auto frontend = weak.Upgrade();
181             if (frontend) {
182                 frontend->UpdatePageData(dataList);
183             }
184         },
185         TaskExecutor::TaskType::UI, "ArkUICardFrontendUpdatePageData"); // eTSCard UI == Main JS/UI/PLATFORM
186 }
187 
UpdatePageData(const std::string& dataList)188 void CardFrontendDeclarative::UpdatePageData(const std::string& dataList)
189 {
190     CHECK_RUN_ON(UI); // eTSCard UI == Main JS/UI/PLATFORM
191     if (!delegate_) {
192         return;
193     }
194     delegate_->UpdatePageData(dataList);
195 }
196 
SetColorMode(ColorMode colorMode)197 void CardFrontendDeclarative::SetColorMode(ColorMode colorMode)
198 {
199     taskExecutor_->PostTask(
200         [weak = AceType::WeakClaim(this), colorMode]() {
201             auto frontend = weak.Upgrade();
202             if (frontend) {
203                 frontend->colorMode_ = colorMode;
204                 if (!frontend->delegate_) {
205                     return;
206                 }
207                 frontend->OnMediaFeatureUpdate();
208             }
209         },
210         TaskExecutor::TaskType::JS, "ArkUICardFrontendSetColorMode");
211 }
212 
RebuildAllPages()213 void CardFrontendDeclarative::RebuildAllPages()
214 {
215 }
216 
OnSurfaceChanged(int32_t width, int32_t height)217 void CardFrontendDeclarative::OnSurfaceChanged(int32_t width, int32_t height)
218 {
219     taskExecutor_->PostTask(
220         [weak = AceType::WeakClaim(this), width, height] {
221             auto frontend = weak.Upgrade();
222             if (frontend) {
223                 frontend->HandleSurfaceChanged(width, height);
224             }
225         },
226         TaskExecutor::TaskType::JS, "ArkUICardFrontendSurfaceChanged");
227 }
228 
HandleSurfaceChanged(int32_t width, int32_t height)229 void CardFrontendDeclarative::HandleSurfaceChanged(int32_t width, int32_t height)
230 {
231     CHECK_RUN_ON(JS);
232     OnMediaFeatureUpdate();
233 }
234 
OnMediaFeatureUpdate()235 void CardFrontendDeclarative::OnMediaFeatureUpdate()
236 {
237     CHECK_RUN_ON(JS);
238 }
239 
240 } // namespace OHOS::Ace
241