1 /*
2  * Copyright (c) 2024 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/cj_frontend/frontend/cj_frontend.h"
17 
18 #include "bridge/cj_frontend/frontend/cj_page_router.h"
19 #include "bridge/js_frontend/js_ace_page.h"
20 #include "core/components_ng/pattern/stage/page_pattern.h"
21 #include "core/gestures/swipe_recognizer.h"
22 #include "core/components/navigator/navigator_component.h"
23 
24 namespace OHOS::Ace::Framework {
InternalInitialize()25 void CJFrontend::InternalInitialize()
26 {
27     LOGE("CJFrontend InternalInitialize begin.");
28     classicRouter_ = MakeRefPtr<CJPageRouter>(WeakClaim(this));
29     pageRouterManager_ = classicRouter_;
30     pageRouterManager_->SetManifestParser(manifestParser_);
31     handler_ = MakeRefPtr<CJEventHandler>(WeakClaim(this));
32 }
33 
AttachPipelineContext(const RefPtr<PipelineBase> & context)34 void CJFrontend::AttachPipelineContext(const RefPtr<PipelineBase>& context)
35 {
36     CJFrontendAbstract::AttachPipelineContext(context);
37     auto pipeline = DynamicCast<PipelineContext>(context);
38     if (pipeline) {
39         pipeline->RegisterEventHandler(handler_);
40     }
41 }
42 
43 namespace {
44 
45 /*
46  * NOTE:
47  * This function is needed to copy the values from BaseEventInfo
48  * It is observed, that the owner of BaseEventInfo will delete the pointer before it is ultimately
49  * processed by the EventMarker callback. In order to avoid this, a copy of all data needs to be made.
50  */
CopyEventInfo(const BaseEventInfo & info)51 std::shared_ptr<BaseEventInfo> CopyEventInfo(const BaseEventInfo& info)
52 {
53     const auto* touchInfo = TypeInfoHelper::DynamicCast<TouchEventInfo>(&info);
54     if (touchInfo != nullptr) {
55         return std::make_shared<TouchEventInfo>(*touchInfo);
56     }
57 
58     const auto* dragStartInfo = TypeInfoHelper::DynamicCast<DragStartInfo>(&info);
59     if (dragStartInfo != nullptr) {
60         return std::make_shared<DragStartInfo>(*dragStartInfo);
61     }
62 
63     const auto* dragUpdateInfo = TypeInfoHelper::DynamicCast<DragUpdateInfo>(&info);
64     if (dragUpdateInfo != nullptr) {
65         return std::make_shared<DragUpdateInfo>(*dragUpdateInfo);
66     }
67 
68     const auto* dragEndInfo = TypeInfoHelper::DynamicCast<DragEndInfo>(&info);
69     if (dragEndInfo != nullptr) {
70         return std::make_shared<DragEndInfo>(*dragEndInfo);
71     }
72 
73     const auto* clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(&info);
74     if (clickInfo != nullptr) {
75         return std::make_shared<ClickInfo>(*clickInfo);
76     }
77     return nullptr;
78 }
79 
TouchInfoToString(const BaseEventInfo & info,std::string & eventParam)80 void TouchInfoToString(const BaseEventInfo& info, std::string& eventParam)
81 {
82     eventParam.append("{\"touches\":[{");
83     const auto touchInfo = TypeInfoHelper::DynamicCast<TouchEventInfo>(&info);
84     if (touchInfo) {
85         auto touchList = touchInfo->GetTouches();
86         for (const auto& location : touchList) {
87             auto globalLocation = location.GetGlobalLocation();
88             eventParam.append("\"globalX\":")
89                     .append(std::to_string(globalLocation.GetX()))
90                     .append(",\"globalY\":")
91                     .append(std::to_string(globalLocation.GetY()))
92                     .append(",");
93             auto localLocation = location.GetLocalLocation();
94             eventParam.append("\"localX\":")
95                     .append(std::to_string(localLocation.GetX()))
96                     .append(",\"localY\":")
97                     .append(std::to_string(localLocation.GetY()))
98                     .append(",");
99             eventParam.append("\"size\":").append(std::to_string(location.GetSize())).append(",");
100         }
101         if (eventParam.back() == ',') {
102             eventParam.pop_back();
103         }
104         eventParam.append("}],\"changedTouches\":[{");
105         auto changeTouch = touchInfo->GetChangedTouches();
106         for (const auto& change : changeTouch) {
107             auto globalLocation = change.GetGlobalLocation();
108             eventParam.append("\"globalX\":")
109                     .append(std::to_string(globalLocation.GetX()))
110                     .append(",\"globalY\":")
111                     .append(std::to_string(globalLocation.GetY()))
112                     .append(",");
113             auto localLocation = change.GetLocalLocation();
114             eventParam.append("\"localX\":")
115                     .append(std::to_string(localLocation.GetX()))
116                     .append(",\"localY\":")
117                     .append(std::to_string(localLocation.GetY()))
118                     .append(",");
119             eventParam.append("\"size\":").append(std::to_string(change.GetSize())).append(",");
120         }
121         if (eventParam.back() == ',') {
122             eventParam.pop_back();
123         }
124     }
125     eventParam.append("}]}");
126 }
127 
MouseInfoToString(const BaseEventInfo & info,std::string & eventParam)128 void MouseInfoToString(const BaseEventInfo& info, std::string& eventParam)
129 {
130     const auto mouseInfo = TypeInfoHelper::DynamicCast<MouseEventInfo>(&info);
131     eventParam.append("{\"mouse\":{");
132     if (mouseInfo) {
133         auto globalMouse = mouseInfo->GetGlobalMouse();
134         eventParam.append("\"globalX\":")
135                 .append(std::to_string(globalMouse.x))
136                 .append(",\"globalY\":")
137                 .append(std::to_string(globalMouse.y))
138                 .append(",\"globalZ\":")
139                 .append(std::to_string(globalMouse.z))
140                 .append(",\"localX\":")
141                 .append(std::to_string(globalMouse.x))
142                 .append(",\"localY\":")
143                 .append(std::to_string(globalMouse.y))
144                 .append(",\"localZ\":")
145                 .append(std::to_string(globalMouse.z))
146                 .append(",\"deltaX\":")
147                 .append(std::to_string(globalMouse.deltaX))
148                 .append(",\"deltaY\":")
149                 .append(std::to_string(globalMouse.deltaY))
150                 .append(",\"deltaZ\":")
151                 .append(std::to_string(globalMouse.deltaZ))
152                 .append(",\"scrollX\":")
153                 .append(std::to_string(globalMouse.scrollX))
154                 .append(",\"scrollY\":")
155                 .append(std::to_string(globalMouse.scrollY))
156                 .append(",\"scrollZ\":")
157                 .append(std::to_string(globalMouse.scrollZ))
158                 .append(",\"action\":")
159                 .append(std::to_string(static_cast<int32_t>(globalMouse.action)))
160                 .append(",\"button\":")
161                 .append(std::to_string(static_cast<int32_t>(globalMouse.button)))
162                 .append(",\"pressedButtons\":")
163                 .append(std::to_string(globalMouse.pressedButtons));
164     }
165     eventParam.append("}}");
166 }
167 
SwipeInfoToString(const BaseEventInfo & info,std::string & eventParam)168 void SwipeInfoToString(const BaseEventInfo& info, std::string& eventParam)
169 {
170     const auto swipeInfo = TypeInfoHelper::DynamicCast<SwipeEventInfo>(&info);
171     if (swipeInfo != nullptr) {
172         eventParam = swipeInfo->ToJsonParamInfo();
173     }
174 }
175 
176 } // namespace
177 
HandleAsyncEvent(const OHOS::Ace::EventMarker & eventMarker)178 void CJEventHandler::HandleAsyncEvent(const OHOS::Ace::EventMarker& eventMarker)
179 {
180     auto frontend = frontend_.Upgrade();
181     CHECK_NULL_VOID(frontend);
182 
183     LOGI("HandleAsyncEvent pageId: %{private}d, eventId: %{private}s, eventType: %{private}s",
184         eventMarker.GetData().pageId, eventMarker.GetData().eventId.c_str(), eventMarker.GetData().eventType.c_str());
185 
186     std::string param = eventMarker.GetData().GetEventParam();
187     frontend->GetTaskExecutor()->PostTask([eventMarker] {
188             eventMarker.CallUiFunction();
189         }, TaskExecutor::TaskType::UI, "CJHandleAsyncEvent");
190 
191     AccessibilityEvent accessibilityEvent;
192     accessibilityEvent.nodeId = StringUtils::StringToInt(eventMarker.GetData().eventId);
193     accessibilityEvent.eventType = eventMarker.GetData().eventType;
194     frontend->GetAccessibilityManager()->SendAccessibilityAsyncEvent(accessibilityEvent);
195 }
196 
HandleAsyncEvent(const OHOS::Ace::EventMarker & eventMarker,const BaseEventInfo & info)197 void CJEventHandler::HandleAsyncEvent(const OHOS::Ace::EventMarker& eventMarker, const BaseEventInfo& info)
198 {
199     auto frontend = frontend_.Upgrade();
200     CHECK_NULL_VOID(frontend);
201 
202     std::string eventParam;
203     if (eventMarker.GetData().eventType.find("touch") != std::string::npos) {
204         TouchInfoToString(info, eventParam);
205     } else if (eventMarker.GetData().eventType.find("mouse") != std::string::npos) {
206         MouseInfoToString(info, eventParam);
207     } else if (eventMarker.GetData().eventType == "swipe") {
208         SwipeInfoToString(info, eventParam);
209     }
210 
211     LOGD("HandleAsyncEvent pageId: %{public}d, eventId: %{public}s, eventType: %{public}s",
212         eventMarker.GetData().pageId, eventMarker.GetData().eventId.c_str(), eventMarker.GetData().eventType.c_str());
213     std::string param = eventMarker.GetData().GetEventParam();
214     if (eventParam.empty()) {
215         param.append("null");
216     } else {
217         param.append(eventParam);
218     }
219     frontend->GetTaskExecutor()->PostTask([eventMarker, info = CopyEventInfo(info)] {
220             eventMarker.CallUiArgFunction(info.get());
221         }, TaskExecutor::TaskType::UI, "CJHandleAsyncEvent");
222 
223     AccessibilityEvent accessibilityEvent;
224     accessibilityEvent.nodeId = StringUtils::StringToInt(eventMarker.GetData().eventId);
225     accessibilityEvent.eventType = eventMarker.GetData().eventType;
226     frontend->GetAccessibilityManager()->SendAccessibilityAsyncEvent(accessibilityEvent);
227 }
228 
HandleAsyncEvent(const EventMarker & eventMarker,const std::shared_ptr<BaseEventInfo> & info)229 void CJEventHandler::HandleAsyncEvent(const EventMarker& eventMarker, const std::shared_ptr<BaseEventInfo>& info)
230 {
231     auto frontend = frontend_.Upgrade();
232     CHECK_NULL_VOID(frontend);
233 
234     frontend->GetTaskExecutor()->PostTask([eventMarker, info] {
235             eventMarker.CallUiArgFunction(info.get());
236         }, TaskExecutor::TaskType::UI, "CJHandleAsyncEvent");
237 }
238 
HandleAsyncEvent(const EventMarker & eventMarker,int32_t param)239 void CJEventHandler::HandleAsyncEvent(const EventMarker& eventMarker, int32_t param)
240 {
241     auto frontend = frontend_.Upgrade();
242     CHECK_NULL_VOID(frontend);
243 
244     AccessibilityEvent accessibilityEvent;
245     accessibilityEvent.nodeId = StringUtils::StringToInt(eventMarker.GetData().eventId);
246     accessibilityEvent.eventType = eventMarker.GetData().eventType;
247     frontend->GetAccessibilityManager()->SendAccessibilityAsyncEvent(accessibilityEvent);
248 }
249 
HandleAsyncEvent(const EventMarker & eventMarker,const KeyEvent & info)250 void CJEventHandler::HandleAsyncEvent(const EventMarker& eventMarker, const KeyEvent& info)
251 {
252     auto frontend = frontend_.Upgrade();
253     CHECK_NULL_VOID(frontend);
254 
255     AccessibilityEvent accessibilityEvent;
256     accessibilityEvent.nodeId = StringUtils::StringToInt(eventMarker.GetData().eventId);
257     accessibilityEvent.eventType = eventMarker.GetData().eventType;
258     frontend->GetAccessibilityManager()->SendAccessibilityAsyncEvent(accessibilityEvent);
259 }
260 
HandleAsyncEvent(const EventMarker & eventMarker,const std::string & param)261 void CJEventHandler::HandleAsyncEvent(const EventMarker& eventMarker, const std::string& param)
262 {
263     LOGD("HandleAsyncEvent pageId: %{public}d, eventId: %{public}s", eventMarker.GetData().pageId,
264         eventMarker.GetData().eventId.c_str());
265     auto frontend = frontend_.Upgrade();
266     CHECK_NULL_VOID(frontend);
267 
268     std::string fixParam(param);
269     std::string::size_type startPos = param.find_first_of("{");
270     std::string::size_type endPos = param.find_last_of("}");
271     if (startPos != std::string::npos && endPos != std::string::npos && startPos < endPos) {
272         fixParam = fixParam.substr(startPos, endPos - startPos + 1);
273     }
274 
275     frontend->GetTaskExecutor()->PostTask([eventMarker, fixParam] {
276             eventMarker.CallUiStrFunction(fixParam);
277         }, TaskExecutor::TaskType::UI, "CJHandleAsyncEvent");
278 
279     AccessibilityEvent accessibilityEvent;
280     accessibilityEvent.nodeId = StringUtils::StringToInt(eventMarker.GetData().eventId);
281     accessibilityEvent.eventType = eventMarker.GetData().eventType;
282     frontend->GetAccessibilityManager()->SendAccessibilityAsyncEvent(accessibilityEvent);
283 }
284 
HandleSyncEvent(const EventMarker & eventMarker,const KeyEvent & info,bool & result)285 void CJEventHandler::HandleSyncEvent(const EventMarker& eventMarker, const KeyEvent& info, bool& result)
286 {
287     LOGD("HandleSyncEvent pageId: %{public}d, eventId: %{public}s, eventType: %{public}s", eventMarker.GetData().pageId,
288         eventMarker.GetData().eventId.c_str(), eventMarker.GetData().eventType.c_str());
289     auto frontend = frontend_.Upgrade();
290     CHECK_NULL_VOID(frontend);
291 
292     std::string param = std::string("\"")
293             .append(eventMarker.GetData().eventType)
294             .append("\",{\"code\":")
295             .append(std::to_string(static_cast<int32_t>(info.code)))
296             .append(",\"action\":")
297             .append(std::to_string(static_cast<int32_t>(info.action)))
298             .append(",\"repeatCount\":")
299             .append(std::to_string(static_cast<int32_t>(info.repeatTime)))
300             .append(",\"timestamp\":")
301             .append(std::to_string(info.timeStamp.time_since_epoch().count()))
302             .append(",\"key\":\"")
303             .append(info.key)
304             .append("\"},");
305 
306     result = false;
307 
308     AccessibilityEvent accessibilityEvent;
309     accessibilityEvent.nodeId = StringUtils::StringToInt(eventMarker.GetData().eventId);
310     accessibilityEvent.eventType = std::to_string(static_cast<int32_t>(info.code));
311     frontend->GetAccessibilityManager()->SendAccessibilityAsyncEvent(accessibilityEvent);
312 }
313 
HandleSyncEvent(const EventMarker & eventMarker,bool & result)314 void CJEventHandler::HandleSyncEvent(const EventMarker& eventMarker, bool& result)
315 {
316     auto frontend = frontend_.Upgrade();
317     CHECK_NULL_VOID(frontend);
318 
319     result = false;
320 
321     AccessibilityEvent accessibilityEvent;
322     accessibilityEvent.nodeId = StringUtils::StringToInt(eventMarker.GetData().eventId);
323     accessibilityEvent.eventType = eventMarker.GetData().eventType;
324     frontend->GetAccessibilityManager()->SendAccessibilityAsyncEvent(accessibilityEvent);
325 }
326 
HandleSyncEvent(const EventMarker & eventMarker,const std::shared_ptr<BaseEventInfo> & info)327 void CJEventHandler::HandleSyncEvent(
328     const EventMarker& eventMarker, const std::shared_ptr<BaseEventInfo>& info)
329 {
330     auto frontend = frontend_.Upgrade();
331     CHECK_NULL_VOID(frontend);
332 
333     frontend->GetTaskExecutor()->PostTask([eventMarker, info] {
334             eventMarker.CallUiArgFunction(info.get());
335         }, TaskExecutor::TaskType::UI, "CJHandleAsyncEvent");
336 }
337 
HandleSyncEvent(const EventMarker & eventMarker,const BaseEventInfo & info,bool & result)338 void CJEventHandler::HandleSyncEvent(const EventMarker& eventMarker, const BaseEventInfo& info, bool& result)
339 {
340     auto frontend = frontend_.Upgrade();
341     CHECK_NULL_VOID(frontend);
342 
343     AccessibilityEvent accessibilityEvent;
344     accessibilityEvent.nodeId = StringUtils::StringToInt(eventMarker.GetData().eventId);
345     accessibilityEvent.eventType = eventMarker.GetData().eventType;
346     frontend->GetAccessibilityManager()->SendAccessibilityAsyncEvent(accessibilityEvent);
347 }
348 
HandleSyncEvent(const EventMarker & eventMarker,const std::string & param,std::string & result)349 void CJEventHandler::HandleSyncEvent(
350     const EventMarker& eventMarker, const std::string& param, std::string& result)
351 {
352     auto frontend = frontend_.Upgrade();
353     CHECK_NULL_VOID(frontend);
354 
355     AccessibilityEvent accessibilityEvent;
356     accessibilityEvent.nodeId = StringUtils::StringToInt(eventMarker.GetData().eventId);
357     accessibilityEvent.eventType = eventMarker.GetData().eventType;
358     frontend->GetAccessibilityManager()->SendAccessibilityAsyncEvent(accessibilityEvent);
359 }
360 
HandleSyncEvent(const EventMarker & eventMarker,const std::string & componentId,const int32_t nodeId,const bool isDestroy)361 void CJEventHandler::HandleSyncEvent(
362     const EventMarker& eventMarker, const std::string& componentId, const int32_t nodeId, const bool isDestroy)
363 {
364 }
365 
366 }