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