1 /*
2  * Copyright (c) 2021-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/declarative_frontend/engine/jsi/modules/jsi_router_module.h"
17 
18 #include "base/json/json_util.h"
19 #include "base/log/log.h"
20 #include "frameworks/bridge/common/utils/engine_helper.h"
21 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h"
22 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
23 #include "frameworks/core/common/container.h"
24 
25 namespace OHOS::Ace::Framework {
26 
DeclarativeParseRouteUrl(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & key)27 std::string DeclarativeParseRouteUrl(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg,
28     const std::string& key)
29 {
30     std::string argStr = arg->GetJsonString(runtime);
31     if (argStr.empty()) {
32         return argStr;
33     }
34 
35     std::string pageRoute;
36     std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(argStr);
37     if (argsPtr != nullptr && argsPtr->GetValue(key) != nullptr && argsPtr->GetValue(key)->IsString()) {
38         pageRoute = argsPtr->GetValue(key)->GetString();
39     }
40 
41     return pageRoute;
42 }
43 
DeclarativeParseRouteParams(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & key)44 std::string DeclarativeParseRouteParams(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg,
45     const std::string& key)
46 {
47     std::string argStr = arg->GetJsonString(runtime);
48     std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(argStr);
49     std::string params;
50     if (argsPtr != nullptr && argsPtr->Contains(key) && argsPtr->GetValue(key)->IsObject()) {
51         params = argsPtr->GetValue(key)->ToString();
52     }
53     return params;
54 }
55 
PagePush(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)56 shared_ptr<JsValue> PagePush(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
57     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
58 {
59     if (argc != 1) {
60         return runtime->NewNull();
61     }
62 
63     std::string uri = DeclarativeParseRouteUrl(runtime, argv[0], ROUTE_KEY_URI);
64     std::string params = DeclarativeParseRouteParams(runtime, argv[0], ROUTE_KEY_PARAMS);
65     auto delegate = EngineHelper::GetCurrentDelegate();
66     if (delegate == nullptr) {
67         return runtime->NewNull();
68     }
69 
70     delegate->Push(uri, params);
71     return runtime->NewNull();
72 }
73 
PageReplace(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)74 shared_ptr<JsValue> PageReplace(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
75     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
76 {
77     if (argc != 1) {
78         return runtime->NewNull();
79     }
80 
81     std::string uri = DeclarativeParseRouteUrl(runtime, argv[0], ROUTE_KEY_URI);
82     std::string params = DeclarativeParseRouteParams(runtime, argv[0], ROUTE_KEY_PARAMS);
83     auto delegate = EngineHelper::GetCurrentDelegate();
84     if (delegate == nullptr) {
85         return runtime->NewNull();
86     }
87 
88     delegate->Replace(uri, params);
89     return runtime->NewNull();
90 }
91 
PageBack(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)92 shared_ptr<JsValue> PageBack(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
93     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
94 {
95     if (argc != 1 && argc != 0) {
96         return runtime->NewNull();
97     }
98 
99     std::string uri;
100     std::string params;
101     if (argc == 1) {
102         uri = DeclarativeParseRouteUrl(runtime, argv[0], ROUTE_KEY_URI);
103         params = DeclarativeParseRouteParams(runtime, argv[0], ROUTE_KEY_PARAMS);
104     }
105     auto delegate = EngineHelper::GetCurrentDelegate();
106     if (delegate == nullptr) {
107         return runtime->NewNull();
108     }
109 
110     delegate->Back(uri, params);
111     return runtime->NewNull();
112 }
113 
PageClear(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)114 shared_ptr<JsValue> PageClear(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
115     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
116 {
117     auto delegate = EngineHelper::GetCurrentDelegate();
118     if (delegate == nullptr) {
119         return runtime->NewNull();
120     }
121 
122     delegate->Clear();
123     return runtime->NewNull();
124 }
125 
PageGetLength(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)126 shared_ptr<JsValue> PageGetLength(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
127     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
128 {
129     auto delegate = EngineHelper::GetCurrentDelegate();
130     if (delegate == nullptr) {
131         return runtime->NewNull();
132     }
133 
134     int32_t routeLength = delegate->GetStackSize();
135     return runtime->NewString(std::to_string(routeLength));
136 }
137 
PageGetState(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)138 shared_ptr<JsValue> PageGetState(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
139     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
140 {
141     auto delegate = EngineHelper::GetCurrentDelegate();
142     if (delegate == nullptr) {
143         return runtime->NewNull();
144     }
145 
146     int32_t routeIndex = 0;
147     std::string routeName;
148     std::string routePath;
149     delegate->GetState(routeIndex, routeName, routePath);
150     shared_ptr<JsValue> jsState = runtime->NewObject();
151     jsState->SetProperty(runtime, "index", runtime->NewNumber(routeIndex));
152     jsState->SetProperty(runtime, "name", runtime->NewString(routeName));
153     jsState->SetProperty(runtime, "path", runtime->NewString(routePath));
154     return jsState;
155 }
156 
PageGetParams(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)157 shared_ptr<JsValue> PageGetParams(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
158     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
159 {
160     auto delegate = EngineHelper::GetCurrentDelegate();
161     if (delegate == nullptr) {
162         return runtime->NewNull();
163     }
164 
165     std::string paramsStr = delegate->GetParams();
166     if (paramsStr.empty()) {
167         return runtime->NewNull();
168     }
169     return runtime->ParseJson(paramsStr);
170 }
171 
InitRouterModule(const shared_ptr<JsRuntime> & runtime,shared_ptr<JsValue> & moduleObj)172 void InitRouterModule(const shared_ptr<JsRuntime>& runtime, shared_ptr<JsValue>& moduleObj)
173 {
174     moduleObj->SetProperty(runtime, ROUTE_PAGE_PUSH, runtime->NewFunction(PagePush));
175     moduleObj->SetProperty(runtime, ROUTE_PAGE_REPLACE, runtime->NewFunction(PageReplace));
176     moduleObj->SetProperty(runtime, ROUTE_PAGE_BACK, runtime->NewFunction(PageBack));
177     moduleObj->SetProperty(runtime, ROUTE_PAGE_CLEAR, runtime->NewFunction(PageClear));
178     moduleObj->SetProperty(runtime, ROUTE_PAGE_GET_LENGTH, runtime->NewFunction(PageGetLength));
179     moduleObj->SetProperty(runtime, ROUTE_PAGE_GET_STATE, runtime->NewFunction(PageGetState));
180     moduleObj->SetProperty(runtime, ROUTE_PAGE_GET_PARAMS, runtime->NewFunction(PageGetParams));
181 
182     shared_ptr<JsValue> global = runtime->GetGlobal();
183     shared_ptr<JsValue> requireNapiFunc = global->GetProperty(runtime, "requireNapi");
184     if (!requireNapiFunc || !requireNapiFunc->IsFunction(runtime)) {
185         return;
186     }
187     std::vector<shared_ptr<JsValue>> argv = { runtime->NewString("router") };
188     shared_ptr<JsValue> napiObj = requireNapiFunc->Call(runtime, global, argv, argv.size());
189     moduleObj->SetProperty(runtime,
190         ROUTE_ENABLE_ALERT_BEFORE_BACK_PAGE, napiObj->GetProperty(runtime, ROUTE_ENABLE_ALERT_BEFORE_BACK_PAGE));
191     moduleObj->SetProperty(runtime,
192         ROUTE_DISABLE_ALERT_BEFORE_BACK_PAGE, napiObj->GetProperty(runtime, ROUTE_DISABLE_ALERT_BEFORE_BACK_PAGE));
193 }
194 
195 } // namespace OHOS::Ace::Framework
196