• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/quickjs/modules/qjs_router_module.h"
17 
18 #include "base/log/log.h"
19 #include "frameworks/bridge/declarative_frontend/engine/quickjs/qjs_declarative_engine.h"
20 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
21 #include "frameworks/bridge/js_frontend/engine/quickjs/qjs_utils.h"
22 
23 namespace OHOS::Ace::Framework {
24 
JsParseRouteUrl(JSContext * ctx,JSValueConst valObject,const std::string & routerKey)25 std::string JsParseRouteUrl(JSContext* ctx, JSValueConst valObject, const std::string& routerKey)
26 {
27     std::string routeUrl;
28     JSPropertyEnum* pTab = nullptr;
29     uint32_t len = 0;
30     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
31         return routeUrl;
32     }
33     for (uint32_t i = 0; i < len; ++i) {
34         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
35         if (key == nullptr) {
36             JS_FreeAtom(ctx, pTab[i].atom);
37             LOGW("key is null. Ignoring!");
38             continue;
39         }
40         JSValue valItem = JS_GetProperty(ctx, valObject, pTab[i].atom);
41         if (JS_IsString(valItem)) {
42             ScopedString styleVal(ctx, valItem);
43             const char* valStr = styleVal.get();
44             if (strcmp(key, routerKey.c_str()) == 0) {
45                 routeUrl = valStr;
46                 LOGD("routeUrl : %{public}s ", routeUrl.c_str());
47             } else {
48                 LOGE("routeUrl : %{public}s unsupported. Ignoring!", key);
49             }
50         } else {
51             LOGE("value of unsupported type. Ignoring!");
52         }
53         JS_FreeAtom(ctx, pTab[i].atom);
54         JS_FreeCString(ctx, key);
55         JS_FreeValue(ctx, valItem);
56     }
57     js_free(ctx, pTab);
58     return routeUrl;
59 }
60 
JsParseRouteParams(JSContext * ctx,JSValueConst valObject,const std::string & paramsKey)61 std::string JsParseRouteParams(JSContext* ctx, JSValueConst valObject, const std::string& paramsKey)
62 {
63     std::string routeParams;
64     JSPropertyEnum* pTab = nullptr;
65     uint32_t len = 0;
66     if (!CheckAndGetJsProperty(ctx, valObject, &pTab, &len)) {
67         return routeParams;
68     }
69     for (uint32_t i = 0; i < len; ++i) {
70         const char* key = JS_AtomToCString(ctx, pTab[i].atom);
71         if (key == nullptr) {
72             JS_FreeAtom(ctx, pTab[i].atom);
73             LOGW("key is null. Ignoring!");
74             continue;
75         }
76         JSValue valItem = JS_GetProperty(ctx, valObject, pTab[i].atom);
77         if (JS_IsObject(valItem)) {
78             if (strcmp(key, paramsKey.c_str()) == 0) {
79                 routeParams = ScopedString::Stringify(valItem);
80                 LOGD("routeParams : %{public}s ", routeParams.c_str());
81             } else {
82                 LOGE("routeParams : %{public}s unsupported. Ignoring!", key);
83             }
84         } else {
85             LOGE("value of unsupported type. Ignoring!");
86         }
87         JS_FreeAtom(ctx, pTab[i].atom);
88         JS_FreeCString(ctx, key);
89         JS_FreeValue(ctx, valItem);
90     }
91     js_free(ctx, pTab);
92     return routeParams;
93 }
94 
PagePush(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)95 JSValue PagePush(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
96 {
97     if (argc != 1) {
98         LOGE("PagePush args count is invalid");
99         return JS_NULL;
100     }
101 
102     std::string uri = JsParseRouteUrl(ctx, argv[0], ROUTE_KEY_URI);
103     std::string params = JsParseRouteParams(ctx, argv[0], ROUTE_KEY_PARAMS);
104     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
105     if (instance == nullptr) {
106         LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
107         return JS_NULL;
108     }
109     instance->GetDelegate()->Push(uri, params);
110     return JS_NULL;
111 }
112 
PageReplace(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)113 JSValue PageReplace(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
114 {
115     if (argc != 1) {
116         LOGE("PageReplace args count is invalid");
117         return JS_NULL;
118     }
119 
120     std::string uri = JsParseRouteUrl(ctx, argv[0], ROUTE_KEY_URI);
121     std::string params = JsParseRouteParams(ctx, argv[0], ROUTE_KEY_PARAMS);
122     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
123     if (instance == nullptr) {
124         LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
125         return JS_NULL;
126     }
127     instance->GetDelegate()->Replace(uri, params);
128     return JS_NULL;
129 }
130 
PageBack(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)131 JSValue PageBack(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
132 {
133     if (argc != 1 && argc != 0) {
134         LOGE("PageBack args count is invalid");
135         return JS_NULL;
136     }
137 
138     std::string uri = JsParseRouteUrl(ctx, argv[0], ROUTE_KEY_URI);
139     std::string params = JsParseRouteParams(ctx, argv[0], ROUTE_KEY_PARAMS);
140     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
141     if (instance == nullptr) {
142         LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
143         return JS_NULL;
144     }
145     instance->GetDelegate()->Back(uri, params);
146     return JS_NULL;
147 }
148 
PageClear(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)149 JSValue PageClear(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
150 {
151     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
152     if (instance == nullptr) {
153         LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
154         return JS_NULL;
155     }
156     instance->GetDelegate()->Clear();
157     return JS_NULL;
158 }
159 
PageGetLength(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)160 JSValue PageGetLength(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
161 {
162     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
163     if (instance == nullptr) {
164         LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
165         return JS_NULL;
166     }
167     int32_t routeLength = instance->GetDelegate()->GetStackSize();
168     return JS_NewString(ctx, std::to_string(routeLength).c_str());
169 }
170 
PageGetState(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)171 JSValue PageGetState(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
172 {
173     int32_t routeIndex = 0;
174     std::string routeName;
175     std::string routePath;
176     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
177     if (instance == nullptr) {
178         LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
179         return JS_NULL;
180     }
181     instance->GetDelegate()->GetState(routeIndex, routeName, routePath);
182     JSValue jsState = JS_NewObject(ctx);
183     JS_SetPropertyStr(ctx, jsState, "index", JS_NewInt32(ctx, routeIndex));
184     JS_SetPropertyStr(ctx, jsState, "name", JS_NewString(ctx, routeName.c_str()));
185     JS_SetPropertyStr(ctx, jsState, "path", JS_NewString(ctx, routePath.c_str()));
186     return jsState;
187 }
188 
PageGetParams(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)189 JSValue PageGetParams(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
190 {
191     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
192     if (instance == nullptr) {
193         LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
194         return JS_NULL;
195     }
196     std::string paramsStr = instance->GetDelegate()->GetParams();
197     if (paramsStr.empty()) {
198         LOGI("PageGetParams params is null");
199         return JS_NULL;
200     }
201 
202     JSValue paramsRes = JS_ParseJSON(ctx, paramsStr.c_str(), paramsStr.length(), nullptr);
203     return paramsRes;
204 }
205 
PostponePageTransition(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)206 JSValue PostponePageTransition(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
207 {
208     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
209     if (instance == nullptr) {
210         LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
211         return JS_NULL;
212     }
213     instance->GetDelegate()->PostponePageTransition();
214     return JS_NULL;
215 }
216 
LaunchPageTransition(JSContext * ctx,JSValueConst value,int32_t argc,JSValueConst * argv)217 JSValue LaunchPageTransition(JSContext* ctx, JSValueConst value, int32_t argc, JSValueConst* argv)
218 {
219     auto* instance = static_cast<QJSDeclarativeEngineInstance*>(JS_GetContextOpaque(ctx));
220     if (instance == nullptr) {
221         LOGE("Can not cast Context to QJSDeclarativeEngineInstance object.");
222         return JS_NULL;
223     }
224     instance->GetDelegate()->LaunchPageTransition();
225     return JS_NULL;
226 }
227 
InitRouterModule(JSContext * ctx,JSValue & moduleObj)228 void InitRouterModule(JSContext* ctx, JSValue& moduleObj)
229 {
230     JS_SetPropertyStr(ctx, moduleObj, ROUTE_PAGE_PUSH, JS_NewCFunction(ctx, PagePush, ROUTE_PAGE_PUSH, 1));
231     JS_SetPropertyStr(ctx, moduleObj, ROUTE_PAGE_REPLACE, JS_NewCFunction(ctx, PageReplace, ROUTE_PAGE_REPLACE, 1));
232     JS_SetPropertyStr(ctx, moduleObj, ROUTE_PAGE_BACK, JS_NewCFunction(ctx, PageBack, ROUTE_PAGE_BACK, 1));
233     JS_SetPropertyStr(ctx, moduleObj, ROUTE_PAGE_CLEAR, JS_NewCFunction(ctx, PageClear, ROUTE_PAGE_CLEAR, 0));
234     JS_SetPropertyStr(
235         ctx, moduleObj, ROUTE_PAGE_GET_LENGTH, JS_NewCFunction(ctx, PageGetLength, ROUTE_PAGE_GET_LENGTH, 0));
236     JS_SetPropertyStr(
237         ctx, moduleObj, ROUTE_PAGE_GET_STATE, JS_NewCFunction(ctx, PageGetState, ROUTE_PAGE_GET_STATE, 0));
238     JS_SetPropertyStr(
239         ctx, moduleObj, ROUTE_PAGE_GET_PARAMS, JS_NewCFunction(ctx, PageGetParams, ROUTE_PAGE_GET_PARAMS, 0));
240     JS_SetPropertyStr(
241         ctx, moduleObj, ROUTE_POSTPONE, JS_NewCFunction(ctx, PostponePageTransition, ROUTE_POSTPONE, 0));
242 
243     JSValue globalObj = JS_GetGlobalObject(ctx);
244     JSValue requireNapiFunc = JS_GetPropertyStr(ctx, globalObj, "requireNapi");
245     if (!JS_IsFunction(ctx, requireNapiFunc)) {
246         JS_FreeValue(ctx, globalObj);
247         return;
248     }
249     JSValueConst argv[] = { JS_NewString(ctx, "router") };
250     JSValue retVal = JS_Call(ctx, requireNapiFunc, globalObj, countof(argv), argv);
251     JS_SetPropertyStr(ctx, moduleObj,
252         ROUTE_ENABLE_ALERT_BEFORE_BACK_PAGE, JS_GetPropertyStr(ctx, retVal, ROUTE_ENABLE_ALERT_BEFORE_BACK_PAGE));
253     JS_SetPropertyStr(ctx, moduleObj,
254         ROUTE_DISABLE_ALERT_BEFORE_BACK_PAGE, JS_GetPropertyStr(ctx, retVal, ROUTE_DISABLE_ALERT_BEFORE_BACK_PAGE));
255     JS_FreeValue(ctx, retVal);
256     JS_FreeValue(ctx, globalObj);
257 }
258 } // namespace OHOS::Ace::Framework
259