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 "page_manager.h"
17 #include "common/screen.h"
18 #include "components/root_view.h"
19 #include "scope_guard.h"
20 #include "sub_page.h"
21
22 namespace Updater {
23 using namespace OHOS;
GetInstance()24 PageManager &PageManager::GetInstance()
25 {
26 static PageManager instance;
27 return instance;
28 }
29
InitImpl(UxPageInfo & pageInfo,std::string_view entry)30 bool PageManager::InitImpl(UxPageInfo &pageInfo, std::string_view entry)
31 {
32 if (!BasePage::IsPageInfoValid(pageInfo)) {
33 return false;
34 }
35 auto basePage = Page::Create<BasePage>(Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight());
36 if (basePage == nullptr || basePage->GetView() == nullptr) {
37 LOG(ERROR) << "create base page failed";
38 return false;
39 }
40 if (!basePage->BuildPage(pageInfo)) {
41 LOG(ERROR) << "Build page failed";
42 return false;
43 }
44 if (!BuildSubPages(basePage->GetPageId(), basePage, pageInfo.subpages, entry)) {
45 LOG(ERROR) << "Build sub page failed";
46 return false;
47 }
48 basePage->SetVisible(false);
49 OHOS::RootView::GetInstance()->Add(basePage->GetView());
50 if (!pageMap_.emplace(pageInfo.id, basePage).second) {
51 LOG(ERROR) << "base page id duplicated:" << pageInfo.id;
52 return false;
53 }
54 pages_.push_back(basePage);
55 if (pageInfo.id == entry) {
56 mainPage_ = basePage;
57 }
58 return true;
59 }
60
Init(std::vector<UxPageInfo> & pageInfos,std::string_view entry)61 bool PageManager::Init(std::vector<UxPageInfo> &pageInfos, std::string_view entry)
62 {
63 Reset();
64 ON_SCOPE_EXIT(reset) {
65 Reset();
66 };
67 for (auto &pageInfo : pageInfos) {
68 if (!InitImpl(pageInfo, entry)) {
69 return false;
70 }
71 }
72 if (!IsValidPage(mainPage_)) {
73 LOG(ERROR) << "entry " << entry << " is invalid ";
74 return false;
75 }
76 CANCEL_SCOPE_EXIT_GUARD(reset);
77 curPage_ = mainPage_;
78 return true;
79 }
80
BuildSubPages(const std::string & pageId,const std::shared_ptr<Page> & basePage,std::vector<UxSubPageInfo> & subPageInfos,std::string_view entry)81 bool PageManager::BuildSubPages(const std::string &pageId, const std::shared_ptr<Page> &basePage,
82 std::vector<UxSubPageInfo> &subPageInfos, std::string_view entry)
83 {
84 for (auto &subPageInfo : subPageInfos) {
85 if (!SubPage::IsPageInfoValid(subPageInfo)) {
86 return false;
87 }
88 const std::string &subPageId = pageId + ":" + subPageInfo.id;
89 auto subPage = Page::Create<SubPage>(basePage, subPageId);
90 if (subPage == nullptr) {
91 LOG(ERROR) << "create sub page failed";
92 return false;
93 }
94 if (!subPage->BuildSubPage(subPageInfo)) {
95 LOG(ERROR) << "build sub page failed";
96 return false;
97 }
98 if (!pageMap_.emplace(subPageId, subPage).second) {
99 LOG(ERROR) << "sub page id duplicated:" << subPageId;
100 return false;
101 }
102 pages_.push_back(subPage);
103 LOG(INFO) << subPageId << " builded";
104 if (subPageId == entry) {
105 mainPage_ = subPage;
106 }
107 }
108 return true;
109 }
110
IsValidCom(const ComInfo & pageComId) const111 bool PageManager::IsValidCom(const ComInfo &pageComId) const
112 {
113 const std::string &pageId = pageComId.pageId;
114 const std::string &comId = pageComId.comId;
115 auto it = pageMap_.find(pageId);
116 if (it == pageMap_.end() || it->second == nullptr) {
117 LOG(ERROR) << "page id " << pageId << "not valid";
118 return false;
119 }
120 const Page &page = *(it->second);
121 return page.IsValidCom(comId);
122 }
123
IsValidPage(const std::shared_ptr<Page> & pg) const124 bool PageManager::IsValidPage(const std::shared_ptr<Page> &pg) const
125 {
126 return pg != nullptr && pg->IsValid();
127 }
128
ShowPage(const std::string & id)129 bool PageManager::ShowPage(const std::string &id)
130 {
131 if (!IsValidPage(curPage_)) {
132 LOG(ERROR) << "cur page is null";
133 return false;
134 }
135 if (id == curPage_->GetPageId()) {
136 curPage_->SetVisible(true);
137 LOG(WARNING) << "show cur page again";
138 return true;
139 }
140 auto it = pageMap_.find(id);
141 if (it == pageMap_.end()) {
142 LOG(ERROR) << "show page failed, id = " << id;
143 return false;
144 }
145 curPage_->SetVisible(false);
146 EnQueuePage(curPage_);
147 curPage_ = it->second;
148 curPage_->SetVisible(true);
149 return true;
150 }
151
ShowMainPage()152 void PageManager::ShowMainPage()
153 {
154 if (!IsValidPage(mainPage_)) {
155 LOG(ERROR) << "main page invalid, can't show main page";
156 return;
157 }
158 ShowPage(mainPage_->GetPageId());
159 }
160
GoBack()161 void PageManager::GoBack()
162 {
163 if (!IsValidPage(curPage_)) {
164 LOG(ERROR) << "cur page is null";
165 return;
166 }
167 if (pageQueue_.empty()) {
168 LOG(ERROR) << "queue empty, can't go back";
169 return;
170 }
171 curPage_->SetVisible(false);
172 curPage_ = pageQueue_.front();
173 pageQueue_.pop_front();
174 curPage_->SetVisible(true);
175 }
176
operator [](const std::string & id) const177 Page &PageManager::operator[](const std::string &id) const
178 {
179 static BasePage dummy;
180 auto it = pageMap_.find(id);
181 if (it == pageMap_.end() || it->second == nullptr) {
182 return dummy;
183 }
184 return *(it->second);
185 }
186
operator [](const ComInfo & comInfo) const187 ViewProxy &PageManager::operator[](const ComInfo &comInfo) const
188 {
189 return (*this)[comInfo.pageId][comInfo.comId];
190 }
191
EnQueuePage(const std::shared_ptr<Page> & page)192 void PageManager::EnQueuePage(const std::shared_ptr<Page> &page)
193 {
194 if (!IsValidPage(page)) {
195 LOG(ERROR) << "enqueue invalid page";
196 return;
197 }
198 pageQueue_.push_front(page);
199 if (pageQueue_.size() > MAX_PAGE_QUEUE_SZ) {
200 pageQueue_.pop_back();
201 }
202 }
203
Reset()204 void PageManager::Reset()
205 {
206 OHOS::RootView::GetInstance()->RemoveAll();
207 pageQueue_.clear();
208 pageMap_.clear();
209 pages_.clear();
210 curPage_ = nullptr;
211 mainPage_ = nullptr;
212 }
213
214 #ifdef UPDATER_UT
Report()215 std::vector<std::string> PageManager::Report()
216 {
217 std::vector<std::string> result {};
218 for (auto &[id, pg] : pageMap_) {
219 if (pg->IsVisible()) {
220 result.push_back(id);
221 }
222 }
223 std::sort(result.begin(), result.end());
224 return result;
225 }
226 #endif
227 } // namespace Updater
228