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 void PageManager::ShowPage(const std::string &id)
130 {
131 if (!IsValidPage(curPage_)) {
132 LOG(ERROR) << "cur page is null";
133 return;
134 }
135 if (id == curPage_->GetPageId()) {
136 curPage_->SetVisible(true);
137 LOG(WARNING) << "show cur page again";
138 return;
139 }
140 auto it = pageMap_.find(id);
141 if (it == pageMap_.end()) {
142 LOG(ERROR) << "show page failed, id = " << id;
143 return;
144 }
145 curPage_->SetVisible(false);
146 EnQueuePage(curPage_);
147 curPage_ = it->second;
148 curPage_->SetVisible(true);
149 }
150
ShowMainPage()151 void PageManager::ShowMainPage()
152 {
153 if (!IsValidPage(mainPage_)) {
154 LOG(ERROR) << "main page invalid, can't show main page";
155 return;
156 }
157 ShowPage(mainPage_->GetPageId());
158 }
159
GoBack()160 void PageManager::GoBack()
161 {
162 if (!IsValidPage(curPage_)) {
163 LOG(ERROR) << "cur page is null";
164 return;
165 }
166 if (pageQueue_.empty()) {
167 LOG(ERROR) << "queue empty, can't go back";
168 return;
169 }
170 curPage_->SetVisible(false);
171 curPage_ = pageQueue_.front();
172 pageQueue_.pop_front();
173 curPage_->SetVisible(true);
174 }
175
operator [](const std::string & id) const176 Page &PageManager::operator[](const std::string &id) const
177 {
178 static BasePage dummy;
179 auto it = pageMap_.find(id);
180 if (it == pageMap_.end() || it->second == nullptr) {
181 return dummy;
182 }
183 return *(it->second);
184 }
185
operator [](const ComInfo & comInfo) const186 ViewProxy &PageManager::operator[](const ComInfo &comInfo) const
187 {
188 return (*this)[comInfo.pageId][comInfo.comId];
189 }
190
EnQueuePage(const std::shared_ptr<Page> & page)191 void PageManager::EnQueuePage(const std::shared_ptr<Page> &page)
192 {
193 if (!IsValidPage(page)) {
194 LOG(ERROR) << "enqueue invalid page";
195 return;
196 }
197 pageQueue_.push_front(page);
198 if (pageQueue_.size() > MAX_PAGE_QUEUE_SZ) {
199 pageQueue_.pop_back();
200 }
201 }
202
Reset()203 void PageManager::Reset()
204 {
205 OHOS::RootView::GetInstance()->RemoveAll();
206 pageQueue_.clear();
207 pageMap_.clear();
208 pages_.clear();
209 curPage_ = nullptr;
210 mainPage_ = nullptr;
211 }
212
213 #ifdef UPDATER_UT
Report()214 std::vector<std::string> PageManager::Report()
215 {
216 std::vector<std::string> result {};
217 for (auto &[id, pg] : pageMap_) {
218 if (pg->IsVisible()) {
219 result.push_back(id);
220 }
221 }
222 std::sort(result.begin(), result.end());
223 return result;
224 }
225 #endif
226 } // namespace Updater