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 #ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_PAGE_ROUTER_MANAGER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_PAGE_ROUTER_MANAGER_H
18 
19 #include <cstdint>
20 #include <list>
21 #include <string>
22 #include <utility>
23 
24 #include "base/memory/ace_type.h"
25 #include "base/memory/referenced.h"
26 #include "base/thread/task_executor.h"
27 #include "base/utils/noncopyable.h"
28 #include "bridge/declarative_frontend/ng/entry_page_info.h"
29 #include "core/common/router_recover_record.h"
30 #include "core/components_ng/base/frame_node.h"
31 #include "frameworks/bridge/common/manifest/manifest_parser.h"
32 #include "interfaces/inner_api/ace/constants.h"
33 #include "bridge/js_frontend/frontend_delegate.h"
34 
35 namespace OHOS::Ace::NG {
36 
37 using LoadPageCallback = std::function<bool(const std::string&,
38     const std::function<void(const std::string&, int32_t)>&)>;
39 using LoadPageByBufferCallback = std::function<bool(const std::shared_ptr<std::vector<uint8_t>>& content,
40     const std::function<void(const std::string&, int32_t)>&, const std::string& contentName)>;
41 using LoadCardCallback = std::function<bool(const std::string&, int64_t cardId, const std::string&)>;
42 using LoadNamedRouterCallback = std::function<bool(const std::string&, bool isTriggeredByJs)>;
43 using RestoreFullPathInfoCallback = std::function<void(std::unique_ptr<JsonValue>)>;
44 using GetFullPathInfoCallback = std::function<std::unique_ptr<JsonValue>()>;
45 using RestoreNamedRouterInfoCallback = std::function<void(std::unique_ptr<JsonValue>)>;
46 using GetNamedRouterInfoCallback = std::function<std::unique_ptr<JsonValue>()>;
47 using IsNamedRouterNeedPreloadCallback = std::function<bool(const std::string&)>;
48 using PreloadNamedRouterCallback = std::function<void(const std::string&, std::function<void(bool)>&&)>;
49 using UpdateRootComponentCallback = std::function<bool()>;
50 #if defined(PREVIEW)
51 using IsComponentPreviewCallback = std::function<bool()>;
52 #endif
53 
54 enum class RouterMode {
55     STANDARD = 0,
56     SINGLE,
57 };
58 
59 struct RouterPageInfo {
60     std::string url;
61     std::string params;
62     bool recoverable = true;
63     RouterMode routerMode = RouterMode::STANDARD;
64     std::function<void(const std::string&, int32_t)> errorCallback;
65     std::string path;
66     bool isNamedRouterMode = false;
67     std::shared_ptr<std::vector<uint8_t>> content;
68 };
69 
70 class PageRouterManager : public AceType {
71     DECLARE_ACE_TYPE(PageRouterManager, AceType)
72 public:
73     PageRouterManager() = default;
74     ~PageRouterManager() override = default;
75 
76     void RunPage(const std::string& url, const std::string& params);
77     void RunPage(const std::shared_ptr<std::vector<uint8_t>>& content, const std::string& params);
78     void RunPageByNamedRouter(const std::string& name, const std::string& params);
79     UIContentErrorCode RunCard(
80         const std::string& url, const std::string& params, int64_t cardId, const std::string& entryPoint = "");
81 
SetManifestParser(const RefPtr<Framework::ManifestParser> & manifestParser)82     void SetManifestParser(const RefPtr<Framework::ManifestParser>& manifestParser)
83     {
84         manifestParser_ = manifestParser;
85     }
86 
SetLoadJsCallback(LoadPageCallback && callback)87     void SetLoadJsCallback(LoadPageCallback&& callback)
88     {
89         loadJs_ = std::move(callback);
90     }
91 
SetLoadJsByBufferCallback(LoadPageByBufferCallback && callback)92     void SetLoadJsByBufferCallback(LoadPageByBufferCallback&& callback)
93     {
94         loadJsByBuffer_ = std::move(callback);
95     }
96 
SetLoadCardCallback(const LoadCardCallback & callback)97     void SetLoadCardCallback(const LoadCardCallback& callback)
98     {
99         loadCard_ = callback;
100     }
101 
SetLoadNamedRouterCallback(LoadNamedRouterCallback && callback)102     void SetLoadNamedRouterCallback(LoadNamedRouterCallback&& callback)
103     {
104         loadNamedRouter_ = callback;
105     }
106 
SetRestoreFullPathInfoCallback(RestoreFullPathInfoCallback && callback)107     void SetRestoreFullPathInfoCallback(RestoreFullPathInfoCallback&& callback)
108     {
109         restoreFullPathInfo_ = callback;
110     }
111 
SetGetFullPathInfoCallback(GetFullPathInfoCallback && callback)112     void SetGetFullPathInfoCallback(GetFullPathInfoCallback&& callback)
113     {
114         getFullPathInfo_ = callback;
115     }
116 
SetRestoreNamedRouterInfoCallback(RestoreNamedRouterInfoCallback && callback)117     void SetRestoreNamedRouterInfoCallback(RestoreNamedRouterInfoCallback&& callback)
118     {
119         restoreNamedRouterInfo_ = callback;
120     }
121 
SetGetNamedRouterInfoCallback(GetNamedRouterInfoCallback && callback)122     void SetGetNamedRouterInfoCallback(GetNamedRouterInfoCallback&& callback)
123     {
124         getNamedRouterInfo_ = callback;
125     }
126 
SetIsNamedRouterNeedPreloadCallback(IsNamedRouterNeedPreloadCallback && callback)127     void SetIsNamedRouterNeedPreloadCallback(IsNamedRouterNeedPreloadCallback&& callback)
128     {
129         isNamedRouterNeedPreload_ = callback;
130     }
131 
SetPreloadNamedRouterCallback(PreloadNamedRouterCallback && callback)132     void SetPreloadNamedRouterCallback(PreloadNamedRouterCallback&& callback)
133     {
134         preloadNamedRouter_ = callback;
135     }
136 
SetUpdateRootComponentCallback(UpdateRootComponentCallback && callback)137     void SetUpdateRootComponentCallback(UpdateRootComponentCallback&& callback)
138     {
139         updateRootComponent_ = callback;
140     }
141 #if defined(PREVIEW)
SetIsComponentPreview(IsComponentPreviewCallback && callback)142     void SetIsComponentPreview(IsComponentPreviewCallback&& callback)
143     {
144         isComponentPreview_ = callback;
145     }
146 #endif
147 
148     void EnableAlertBeforeBackPage(const std::string& message, std::function<void(int32_t)>&& callback);
149 
150     void DisableAlertBeforeBackPage();
151 
152     // router operation
153     void Push(const RouterPageInfo& target);
154     void PushNamedRoute(const RouterPageInfo& target);
155     bool Pop();
156     void Replace(const RouterPageInfo& target);
157     void ReplaceNamedRoute(const RouterPageInfo& target);
158     void BackWithTarget(const RouterPageInfo& target);
159     void BackToIndexWithTarget(int32_t index, const std::string& params);
160     void Clear();
161     int32_t GetStackSize() const;
162     int32_t GetCurrentPageIndex() const;
163     RouterPageInfo GetPageInfoByIndex(int32_t index, const std::string& params);
164 
165     void GetState(int32_t& index, std::string& name, std::string& path);
166     void GetStateByIndex(int32_t index, std::string& name, std::string& path, std::string& params);
167     void GetStateByUrl(std::string& url, std::vector<Framework::StateInfo>& stateArray);
168 
169     void GetPageNameAndPath(const std::string& url, std::string& name, std::string& path);
170     int32_t GetPageIndex(const WeakPtr<FrameNode>& page);
171 
172     std::string GetParams() const;
173 
174     int32_t GetIndexByUrl(const std::string& url) const;
175 
GetCurrentPageNode()176     RefPtr<FrameNode> GetCurrentPageNode() const
177     {
178         if (pageRouterStack_.empty()) {
179             return nullptr;
180         }
181         return pageRouterStack_.back().Upgrade();
182     }
183 
184     std::string GetCurrentPageUrl();
185 
186     // Get the currently running JS page information in NG structure.
187     RefPtr<Framework::RevSourceMap> GetCurrentPageSourceMap(const RefPtr<AssetManager>& assetManager);
188 
SetIsCard()189     void SetIsCard()
190     {
191         isCardRouter_ = true;
192     }
193 
194     void FlushFrontend();
195 
196     std::unique_ptr<JsonValue> GetStackInfo(ContentInfoType type);
197     std::unique_ptr<JsonValue> GetNamedRouterInfo();
198     std::unique_ptr<JsonValue> GetFullPathInfo();
199 
200     std::pair<RouterRecoverRecord, UIContentErrorCode> RestoreRouterStack(
201         std::unique_ptr<JsonValue> stackInfo, ContentInfoType type);
202     void RestoreNamedRouterInfo(std::unique_ptr<JsonValue> namedRouterInfo);
203     void RestoreFullPathInfo(std::unique_ptr<JsonValue> fullPathInfo);
204 
205     // begin from 1
206     bool IsUnrestoreByIndex(int32_t index);
207 
208 protected:
209     class RouterOptScope {
210     public:
RouterOptScope(PageRouterManager * manager)211         explicit RouterOptScope(PageRouterManager* manager) : manager_(manager)
212         {
213             manager_->inRouterOpt_ = true;
214         }
~RouterOptScope()215         ~RouterOptScope()
216         {
217             manager_->inRouterOpt_ = false;
218         }
219 
220     private:
221         PageRouterManager* manager_ = nullptr;
222     };
223 
224     // page id manage
225     int32_t GenerateNextPageId();
226 
GetLastPageIndex()227     virtual int32_t GetLastPageIndex()
228     {
229         return static_cast<int32_t>(pageRouterStack_.size()) - 1;
230     }
231 
232     std::pair<int32_t, RefPtr<FrameNode>> FindPageInStack(const std::string& url, bool needIgnoreBegin = false);
233     std::pair<int32_t, RefPtr<FrameNode>> FindPageInStackByRouteName(const std::string& name) const;
234     int32_t FindPageInRestoreStack(const std::string& url);
235 
236     void SetPageInfoRouteName(const RefPtr<EntryPageInfo>& info, bool isNamedRouterMode);
237 
238     void LoadOhmUrl(const RouterPageInfo& target);
239     void PushOhmUrl(const RouterPageInfo& target);
240     void ReplaceOhmUrl(const RouterPageInfo& target);
241     void StartPush(const RouterPageInfo& target);
242     void StartReplace(const RouterPageInfo& target);
243     void StartBack(const RouterPageInfo& target);
244     void StartBackToIndex(int32_t index, const std::string& params);
245     bool StartPop();
246     void StartRestore(const RouterPageInfo& target);
247     void BackCheckAlert(const RouterPageInfo& target);
248     void BackToIndexCheckAlert(int32_t index, const std::string& params);
249     void StartClean();
250     void CleanPageOverlay();
251 
252     enum class RestorePageDestination : int32_t {
253         TOP = 0,         // restore page to pageRouterStack_'s top
254         BELLOW_TOP = 1,  // restore page bellow pageRouterStack_'s top
255         BOTTOM = 2,      // restore page to pageRouterStack_'s bottom
256     };
257 
258     // page operations
259     virtual void LoadPage(int32_t pageId, const RouterPageInfo& target,
260         bool needHideLast = true, bool needTransition = true, bool isPush = false);
261     void MovePageToFront(int32_t index, const RefPtr<FrameNode>& pageNode, const RouterPageInfo& target,
262         bool needHideLast, bool forceShowCurrent = false, bool needTransition = true);
263     void RefreshPageIndex(std::list<WeakPtr<FrameNode>>::iterator startIter, int32_t startIndex);
264     void RefreshAllPageIndex();
265     void RestorePageWithTarget(int32_t index, bool removeRestorePages,
266         const RouterPageInfo& target, RestorePageDestination dest, bool needTransition = true);
267     void RestorePageWithTargetInner(
268         const RouterPageInfo& target, RestorePageDestination dest, bool needTransition = true);
269     void StartRestorePageWithTarget(const RouterPageInfo& target, std::function<void()>&& finishCallback,
270         RestorePageDestination dest, bool needTransition);
271 
272     void PopPage(const std::string& params, bool needShowNext, bool needTransition, bool needReplaceParams = true);
273     void PopPageToIndex(int32_t index, const std::string& params, bool needShowNext, bool needTransition);
274     void DealReplacePage(const RouterPageInfo& target);
275     virtual void ReplacePageInNewLifecycle(const RouterPageInfo& target);
276 
277     static bool OnPageReady(const RefPtr<FrameNode>& pageNode, bool needHideLast, bool needTransition,
278         bool isCardRouter = false, int64_t cardId = 0);
279     static bool OnPopPage(bool needShowNext, bool needTransition);
280     static bool OnPopPageToIndex(int32_t index, bool needShowNext, bool needTransition);
281     static bool OnCleanPageStack();
282 
283     UIContentErrorCode LoadCard(int32_t pageId, const RouterPageInfo& target, const std::string& params, int64_t cardId,
284         bool isRestore = false, bool needHideLast = true, const std::string& entryPoint = "");
285 
286     bool CheckIndexValid(int32_t index) const;
287     bool CheckOhmUrlValid(const std::string& ohmUrl);
288     void ThrowError(const std::string& msg, int32_t code);
289 
290     bool TryPreloadNamedRouter(const std::string& name, std::function<void()>&& finishCallback);
291     void PushNamedRouteInner(const RouterPageInfo& target);
292     void ReplaceNamedRouteInner(const RouterPageInfo& target);
293     void RunPageByNamedRouterInner(const std::string& name, const std::string& params);
294 
295     RefPtr<FrameNode> CreatePage(int32_t pageId, const RouterPageInfo& target);
296     void RestoreOhmUrl(const RouterPageInfo& target, std::function<void()>&& finishCallback,
297         RestorePageDestination dest, bool needTransition);
298     void PushPageToTop(RefPtr<FrameNode>& pageNode, std::function<void()>&& finishCallback, bool needTransition);
299     void InsertPageBellowTop(RefPtr<FrameNode>& pageNode, std::function<void()>&& finishCallback);
300     void InsertPageToBottom(RefPtr<FrameNode>& pageNode, std::function<void()>&& finishCallback);
301     void LoadOhmUrlPage(const std::string& url, std::function<void()>&& finishCallback,
302         const std::function<void(const std::string& errorMsg, int32_t errorCode)>& errorCallback,
303         const std::string& finishCallbackTaskName, const std::string& errorCallbackTaskName);
304 
305     RefPtr<Framework::ManifestParser> manifestParser_;
306 
307     enum class InsertPageProcessingType : int32_t {
308         NONE = 0,
309         INSERT_BELLOW_TOP = 1,
310         INSERT_BOTTOM = 2,
311     };
312     InsertPageProcessingType insertPageProcessingType_ = InsertPageProcessingType::NONE;
313     bool inRouterOpt_ = false;
314     LoadPageCallback loadJs_;
315     LoadPageByBufferCallback loadJsByBuffer_;
316     LoadCardCallback loadCard_;
317     LoadNamedRouterCallback loadNamedRouter_;
318     GetFullPathInfoCallback getFullPathInfo_;
319     RestoreFullPathInfoCallback restoreFullPathInfo_;
320     GetNamedRouterInfoCallback getNamedRouterInfo_;
321     RestoreNamedRouterInfoCallback restoreNamedRouterInfo_;
322     IsNamedRouterNeedPreloadCallback isNamedRouterNeedPreload_;
323     PreloadNamedRouterCallback preloadNamedRouter_;
324     UpdateRootComponentCallback updateRootComponent_;
325     bool isCardRouter_ = false;
326     int32_t pageId_ = 0;
327     std::list<WeakPtr<FrameNode>> pageRouterStack_;
328     std::list<RouterRecoverRecord> restorePageStack_;
329     RouterPageInfo ngBackTarget_;
330     bool isNewPageReplacing_ = false;
331 #if defined(PREVIEW)
332     IsComponentPreviewCallback isComponentPreview_;
333 #endif
334 
335     ACE_DISALLOW_COPY_AND_MOVE(PageRouterManager);
336 };
337 
338 } // namespace OHOS::Ace::NG
339 
340 #endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_PAGE_ROUTER_MANAGER_H
341