• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "bridge/declarative_frontend/jsview/js_view_stack_processor.h"
17 
18 #include "bridge/declarative_frontend/engine/bindings.h"
19 #include "bridge/declarative_frontend/engine/js_execution_scope_defines.h"
20 #include "bridge/declarative_frontend/engine/js_types.h"
21 #include "bridge/declarative_frontend/jsview/models/view_stack_model_impl.h"
22 #include "bridge/declarative_frontend/view_stack_processor.h"
23 #include "core/common/container.h"
24 #include "core/components_ng/base/view_stack_model.h"
25 #include "core/components_ng/base/view_stack_model_ng.h"
26 #include "core/components_ng/base/view_stack_processor.h"
27 #include "foundation/arkui/ace_engine/frameworks/core/common/ace_application_info.h"
28 #include "frameworks/core/common/layout_inspector.h"
29 #include "frameworks/core/pipeline/base/element_register.h"
30 
31 namespace OHOS::Ace {
32 
GetInstance()33 ViewStackModel* ViewStackModel::GetInstance()
34 {
35 #ifdef NG_BUILD
36     static NG::ViewStackModelNG instance;
37     return &instance;
38 #else
39     if (Container::IsCurrentUseNewPipeline()) {
40         static NG::ViewStackModelNG instance;
41         return &instance;
42     } else {
43         static Framework::ViewStackModelImpl instance;
44         return &instance;
45     }
46 #endif
47 }
48 
49 } // namespace OHOS::Ace
50 namespace OHOS::Ace::Framework {
51 
JSVisualState(const JSCallbackInfo & info)52 void JSViewStackProcessor::JSVisualState(const JSCallbackInfo& info)
53 {
54     if ((info.Length() < 1) || (!info[0]->IsString())) {
55         ViewStackModel::GetInstance()->ClearVisualState();
56         return;
57     }
58 
59     std::string state = info[0]->ToString();
60     VisualState visualState = JSViewStackProcessor::StringToVisualState(state);
61     ViewStackModel::GetInstance()->SetVisualState(visualState);
62 }
63 
64 // public static emthods exposed to JS
JSBind(BindingTarget globalObj)65 void JSViewStackProcessor::JSBind(BindingTarget globalObj)
66 {
67     JSClass<JSViewStackProcessor>::Declare("ViewStackProcessor");
68     MethodOptions opt = MethodOptions::NONE;
69 
70     JSClass<JSViewStackProcessor>::StaticMethod(
71         "AllocateNewElmetIdForNextComponent", &JSViewStackProcessor::JsAllocateNewElmetIdForNextComponent, opt);
72     JSClass<JSViewStackProcessor>::StaticMethod(
73         "StartGetAccessRecordingFor", &JSViewStackProcessor::JsStartGetAccessRecordingFor, opt);
74     JSClass<JSViewStackProcessor>::StaticMethod(
75         "SetElmtIdToAccountFor", &JSViewStackProcessor::JsSetElmtIdToAccountFor, opt);
76     JSClass<JSViewStackProcessor>::StaticMethod(
77         "GetElmtIdToAccountFor", &JSViewStackProcessor::JsGetElmtIdToAccountFor, opt);
78     JSClass<JSViewStackProcessor>::StaticMethod(
79         "StopGetAccessRecording", &JSViewStackProcessor::JsStopGetAccessRecording, opt);
80     JSClass<JSViewStackProcessor>::StaticMethod(
81         "ImplicitPopBeforeContinue", &JSViewStackProcessor::JsImplicitPopBeforeContinue, opt);
82     JSClass<JSViewStackProcessor>::StaticMethod("visualState", JSVisualState, opt);
83     JSClass<JSViewStackProcessor>::StaticMethod("MakeUniqueId", &JSViewStackProcessor::JSMakeUniqueId, opt);
84     JSClass<JSViewStackProcessor>::StaticMethod("UsesNewPipeline", &JSViewStackProcessor::JsUsesNewPipeline, opt);
85     JSClass<JSViewStackProcessor>::StaticMethod("getApiVersion", &JSViewStackProcessor::JsGetApiVersion, opt);
86     JSClass<JSViewStackProcessor>::StaticMethod("GetAndPushFrameNode", &JSViewStackProcessor::JsGetAndPushFrameNode);
87     JSClass<JSViewStackProcessor>::StaticMethod("moveDeletedElmtIds", &JSViewStackProcessor::JsMoveDeletedElmtIds);
88     JSClass<JSViewStackProcessor>::StaticMethod(
89         "scheduleUpdateOnNextVSync", &JSViewStackProcessor::JSScheduleUpdateOnNextVSync);
90     JSClass<JSViewStackProcessor>::StaticMethod("PushPrebuildCompCmd",
91         &JSViewStackProcessor::JsPushPrebuildCompCmd, opt);
92     JSClass<JSViewStackProcessor>::StaticMethod("CheckIsPrebuildTimeout",
93         &JSViewStackProcessor::JsCheckIsPrebuildTimeout, opt);
94     JSClass<JSViewStackProcessor>::StaticMethod("sendStateInfo", &JSViewStackProcessor::JsSendStateInfo);
95 #ifdef ACE_STATIC
96     JSClass<JSViewStackProcessor>::StaticMethod("push", &JSViewStackProcessor::JsPush, opt);
97     JSClass<JSViewStackProcessor>::StaticMethod("pop", &JSViewStackProcessor::JsPop, opt);
98 #endif
99     JSClass<JSViewStackProcessor>::Bind<>(globalObj);
100 }
101 
StringToVisualState(const std::string & stateString)102 VisualState JSViewStackProcessor::StringToVisualState(const std::string& stateString)
103 {
104     if (stateString == "normal") {
105         return VisualState::NORMAL;
106     }
107     if (stateString == "focused") {
108         return VisualState::FOCUSED;
109     }
110     if (stateString == "pressed" || stateString == "clicked") {
111         return VisualState::PRESSED;
112     }
113     if (stateString == "disabled") {
114         return VisualState::DISABLED;
115     }
116     if (stateString == "hover") {
117         return VisualState::HOVER;
118     }
119     if (stateString == "selected") {
120         return VisualState::SELECTED;
121     }
122     LOGE("Unknown visual state \"%{public}s\", resetting to UNDEFINED", stateString.c_str());
123     return VisualState::NOTSET;
124 }
125 
JsStartGetAccessRecordingFor(ElementIdType elmtId)126 void JSViewStackProcessor::JsStartGetAccessRecordingFor(ElementIdType elmtId)
127 {
128     ViewStackModel::GetInstance()->StartGetAccessRecordingFor(elmtId);
129 }
130 
JsGetElmtIdToAccountFor()131 int32_t JSViewStackProcessor::JsGetElmtIdToAccountFor()
132 {
133     return ViewStackModel::GetInstance()->GetElmtIdToAccountFor();
134 }
135 
JsSetElmtIdToAccountFor(ElementIdType elmtId)136 void JSViewStackProcessor::JsSetElmtIdToAccountFor(ElementIdType elmtId)
137 {
138     ViewStackModel::GetInstance()->SetElmtIdToAccountFor(elmtId);
139 }
140 
JsStopGetAccessRecording()141 void JSViewStackProcessor::JsStopGetAccessRecording()
142 {
143     return ViewStackModel::GetInstance()->StopGetAccessRecording();
144 }
145 
JsImplicitPopBeforeContinue()146 void JSViewStackProcessor::JsImplicitPopBeforeContinue()
147 {
148     ViewStackModel::GetInstance()->ImplicitPopBeforeContinue();
149 }
150 
JSMakeUniqueId(const JSCallbackInfo & info)151 void JSViewStackProcessor::JSMakeUniqueId(const JSCallbackInfo& info)
152 {
153     const auto result = ElementRegister::GetInstance()->MakeUniqueId();
154     info.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(result)));
155 }
JsMoveDeletedElmtIds(const JSCallbackInfo & info)156 void JSViewStackProcessor::JsMoveDeletedElmtIds(const JSCallbackInfo& info)
157 {
158     auto jsArrInfo = info[0];
159     if (!jsArrInfo->IsArray()) {
160         return;
161     }
162     JSRef<JSArray> jsArr = JSRef<JSArray>::Cast(jsArrInfo);
163 
164     RemovedElementsType removedElements;
165     ElementRegister::GetInstance()->MoveRemovedItems(removedElements);
166     size_t index = jsArr->Length();
167     for (const auto& rmElmtId : removedElements) {
168         jsArr->SetValueAt(index++, JSRef<JSVal>::Make(ToJSValue(rmElmtId)));
169     }
170 }
171 
172 // Initiates a frame request to RosenWindow and handles the callback from the Vsync request
JSScheduleUpdateOnNextVSync(const JSCallbackInfo & info)173 void JSViewStackProcessor::JSScheduleUpdateOnNextVSync(const JSCallbackInfo& info)
174 {
175     // Get the correct container
176     int32_t containerId = -1;
177     if (info.Length() > 1 && info[1]->IsNumber()) {
178         containerId = info[1]->ToNumber<int32_t>();
179     } else {
180         LOGE("ERROR: JSScheduleUpdateOnNextVSync() no containerId provided.");
181         return;
182     }
183 
184     if (containerId < 0) {
185         LOGE("ERROR: JSScheduleUpdateOnNextVSync() invalid containerId.");
186         return;
187     }
188 
189     auto container = Container::GetContainer(containerId);
190     if (!container) {
191         LOGE("JSScheduleUpdateOnNextVSync container is null");
192         return;
193     }
194     auto context = container->GetPipelineContext();
195     if (!context) {
196         LOGE("JSScheduleUpdateOnNextVSync context is null");
197         return;
198     }
199 
200     if (info[0]->IsFunction()) {
201         auto flushTSFunc = [execCtx = info.GetExecutionContext(),
202             func = JSRef<JSFunc>::Cast(info[0])](int32_t containerId) -> bool {
203             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, false);
204             JSRef<JSVal> jsId = JSRef<JSVal>::Make(ToJSValue(containerId));
205             JSRef<JSVal> retVal = func->Call(JSRef<JSObject>(), 1, &jsId);
206             if (!retVal->IsBoolean()) {
207                 LOGE("JSScheduleUpdateOnNextVSync: flushTSFunc retVal is not boolean.");
208                 return false;
209             }
210             return retVal->ToBoolean();
211         };
212         context->SetFlushTSUpdates(std::move(flushTSFunc));
213     } else {
214         context->SetFlushTSUpdates(nullptr);
215     }
216 }
217 
JsSendStateInfo(const std::string & stateInfo)218 void JSViewStackProcessor::JsSendStateInfo(const std::string& stateInfo)
219 {
220 #if defined(PREVIEW) || !defined(OHOS_PLATFORM)
221     return;
222 #else
223     if (!LayoutInspector::GetStateProfilerStatus()) {
224         return;
225     }
226     auto container = Container::CurrentSafely();
227     CHECK_NULL_VOID(container);
228     auto pipeline = container->GetPipelineContext();
229     CHECK_NULL_VOID(pipeline);
230     auto info = JsonUtil::ParseJsonString(stateInfo);
231     info->Put("timeStamp", GetCurrentTimestampMicroSecond());
232     info->Put("vsyncID", (int32_t)pipeline->GetFrameCount());
233     info->Put("processID", getpid());
234     info->Put("windowID", (int32_t)pipeline->GetWindowId());
235     TAG_LOGD(AceLogTag::ACE_STATE_MGMT, "ArkUI SendStateInfo %{public}s", info->ToString().c_str());
236     LayoutInspector::SendMessage(info->ToString());
237 #endif
238 }
239 
240 /**
241  * return true of current Container uses new Pipeline
242  */
JsUsesNewPipeline()243 bool JSViewStackProcessor::JsUsesNewPipeline()
244 {
245     auto container = Container::Current();
246     return container ? container->IsUseNewPipeline() : AceApplicationInfo::GetInstance().IsUseNewPipeline();
247 }
248 
249 /**
250  * return the API version specified in the manifest.json
251  */
JsGetApiVersion()252 int32_t JSViewStackProcessor::JsGetApiVersion()
253 {
254     return AceApplicationInfo::GetInstance().GetApiTargetVersion();
255 }
256 
JsGetAndPushFrameNode(const JSCallbackInfo & info)257 void JSViewStackProcessor::JsGetAndPushFrameNode(const JSCallbackInfo& info)
258 {
259     if (info.Length() < 2) {
260         return;
261     }
262     if (!info[0]->IsString() || !info[1]->IsNumber()) {
263         return;
264     }
265     ViewStackModel::GetInstance()->GetAndPushFrameNode(info[0]->ToString(), info[1]->ToNumber<int32_t>());
266 }
267 
JsPushPrebuildCompCmd(const JSCallbackInfo & info)268 void JSViewStackProcessor::JsPushPrebuildCompCmd(const JSCallbackInfo& info)
269 {
270     ViewStackModel::GetInstance()->PushPrebuildCompCmd();
271 }
272 
JsCheckIsPrebuildTimeout()273 bool JSViewStackProcessor::JsCheckIsPrebuildTimeout()
274 {
275     return ViewStackModel::GetInstance()->CheckIsPrebuildTimeout();
276 }
277 
278 #ifdef ACE_STATIC
JsPush(const JSCallbackInfo & info)279 void JSViewStackProcessor::JsPush(const JSCallbackInfo &info)
280 {
281     if (info.Length() < 1) {
282         return;
283     }
284     if (!info[0]->IsNumber()) {
285         return;
286     }
287 
288     return ViewStackModel::GetInstance()->PushPtr(info[0]->ToNumber<int64_t>());
289 }
290 
JsPop()291 void JSViewStackProcessor::JsPop()
292 {
293     return ViewStackModel::GetInstance()->Pop();
294 }
295 #endif
296 } // namespace OHOS::Ace::Framework
297