• 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 "frameworks/bridge/declarative_frontend/jsview/js_interactable_view.h"
17 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
18 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
19 #endif
20 
21 #include "base/log/ace_scoring_log.h"
22 #include "base/log/log_wrapper.h"
23 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
24 #include "bridge/declarative_frontend/engine/functions/js_hover_function.h"
25 #include "bridge/declarative_frontend/engine/functions/js_key_function.h"
26 #include "bridge/declarative_frontend/engine/js_execution_scope_defines.h"
27 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_frame_node_bridge.h"
28 #include "bridge/declarative_frontend/jsview/js_pan_handler.h"
29 #include "bridge/declarative_frontend/jsview/js_touch_handler.h"
30 #include "bridge/declarative_frontend/jsview/js_utils.h"
31 #include "bridge/declarative_frontend/view_stack_processor.h"
32 #include "core/common/container.h"
33 #include "core/components/gesture_listener/gesture_listener_component.h"
34 #include "core/components_ng/base/view_abstract_model.h"
35 #include "core/components_ng/base/view_stack_processor.h"
36 #include "core/gestures/click_recognizer.h"
37 #include "core/pipeline/base/single_child.h"
38 #include "core/pipeline/pipeline_context.h"
39 
40 #ifdef PLUGIN_COMPONENT_SUPPORTED
41 #include "core/common/plugin_manager.h"
42 #endif
43 
44 namespace OHOS::Ace::Framework {
45 
JsOnTouch(const JSCallbackInfo & args)46 void JSInteractableView::JsOnTouch(const JSCallbackInfo& args)
47 {
48     if (args[0]->IsUndefined() && IsDisableEventVersion()) {
49         ViewAbstractModel::GetInstance()->DisableOnTouch();
50         return;
51     }
52     if (!args[0]->IsFunction()) {
53         return;
54     }
55     EcmaVM* vm = args.GetVm();
56     CHECK_NULL_VOID(vm);
57     auto jsOnTouchFunc = JSRef<JSFunc>::Cast(args[0]);
58     if (jsOnTouchFunc->IsEmpty()) {
59         return;
60     }
61     auto jsOnTouchFuncLocalHandle = jsOnTouchFunc->GetLocalHandle();
62     auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
63     auto onTouch = [vm, execCtx = args.GetExecutionContext(),
64                        func = panda::CopyableGlobal(vm, jsOnTouchFuncLocalHandle),
65                        node = frameNode](TouchEventInfo& info) {
66         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
67         ACE_SCORING_EVENT("onTouch");
68         PipelineContext::SetCallBackNode(node);
69         auto eventObj = NG::FrameNodeBridge::CreateTouchEventInfo(vm, info);
70         panda::Local<panda::JSValueRef> params[1] = { eventObj };
71         func->Call(vm, func.ToLocal(), params, 1);
72     };
73     ViewAbstractModel::GetInstance()->SetOnTouch(std::move(onTouch));
74 }
75 
JsOnKey(const JSCallbackInfo & args)76 void JSInteractableView::JsOnKey(const JSCallbackInfo& args)
77 {
78     if (args[0]->IsUndefined() && IsDisableEventVersion()) {
79         ViewAbstractModel::GetInstance()->DisableOnKeyEvent();
80         return;
81     }
82     if (!args[0]->IsFunction()) {
83         return;
84     }
85     RefPtr<JsKeyFunction> JsOnKeyEvent = AceType::MakeRefPtr<JsKeyFunction>(JSRef<JSFunc>::Cast(args[0]));
86     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
87     auto onKeyEvent = [execCtx = args.GetExecutionContext(), func = std::move(JsOnKeyEvent), node = frameNode](
88                           KeyEventInfo& info) {
89         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
90         ACE_SCORING_EVENT("onKey");
91         PipelineContext::SetCallBackNode(node);
92         func->Execute(info);
93     };
94     ViewAbstractModel::GetInstance()->SetOnKeyEvent(std::move(onKeyEvent));
95 }
96 
JsOnKeyPreIme(const JSCallbackInfo & args)97 void JSInteractableView::JsOnKeyPreIme(const JSCallbackInfo& args)
98 {
99     if (args[0]->IsUndefined()) {
100         ViewAbstractModel::GetInstance()->DisableOnKeyPreIme();
101         return;
102     }
103     if (!args[0]->IsFunction()) {
104         return;
105     }
106     RefPtr<JsKeyFunction> JsOnPreImeEvent = AceType::MakeRefPtr<JsKeyFunction>(JSRef<JSFunc>::Cast(args[0]));
107     auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
108     auto onPreImeEvent = [execCtx = args.GetExecutionContext(), func = std::move(JsOnPreImeEvent), node = frameNode](
109                           KeyEventInfo& info) -> bool {
110         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, false);
111         ACE_SCORING_EVENT("onKeyPreIme");
112         PipelineContext::SetCallBackNode(node);
113         auto ret = func->ExecuteWithValue(info);
114         return ret->IsBoolean() ? ret->ToBoolean() : false;
115     };
116     ViewAbstractModel::GetInstance()->SetOnKeyPreIme(std::move(onPreImeEvent));
117 }
118 
JsOnHover(const JSCallbackInfo & info)119 void JSInteractableView::JsOnHover(const JSCallbackInfo& info)
120 {
121     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
122         ViewAbstractModel::GetInstance()->DisableOnHover();
123         return;
124     }
125     if (!info[0]->IsFunction()) {
126         return;
127     }
128     RefPtr<JsHoverFunction> jsOnHoverFunc = AceType::MakeRefPtr<JsHoverFunction>(JSRef<JSFunc>::Cast(info[0]));
129     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
130     auto onHover = [execCtx = info.GetExecutionContext(), func = std::move(jsOnHoverFunc), node = frameNode](
131                        bool isHover, HoverInfo& hoverInfo) {
132         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
133         ACE_SCORING_EVENT("onHover");
134         PipelineContext::SetCallBackNode(node);
135         func->HoverExecute(isHover, hoverInfo);
136     };
137     ViewAbstractModel::GetInstance()->SetOnHover(std::move(onHover));
138 }
139 
JsOnPan(const JSCallbackInfo & args)140 void JSInteractableView::JsOnPan(const JSCallbackInfo& args)
141 {
142     if (args[0]->IsObject()) {
143 #ifndef NG_BUILD
144         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
145         JSPanHandler* handler = obj->Unwrap<JSPanHandler>();
146         if (handler) {
147             handler->CreateComponent(args);
148         }
149 #endif
150     }
151 }
152 
JsOnDelete(const JSCallbackInfo & info)153 void JSInteractableView::JsOnDelete(const JSCallbackInfo& info)
154 {
155     if (info[0]->IsFunction()) {
156         RefPtr<JsFunction> jsOnDeleteFunc =
157             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
158         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
159         auto onDelete = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDeleteFunc), node = frameNode]() {
160             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
161             ACE_SCORING_EVENT("onDelete");
162             PipelineContext::SetCallBackNode(node);
163             func->Execute();
164         };
165         ViewAbstractModel::GetInstance()->SetOnDelete(std::move(onDelete));
166     }
167 }
168 
JsTouchable(const JSCallbackInfo & info)169 void JSInteractableView::JsTouchable(const JSCallbackInfo& info)
170 {
171     if (info[0]->IsBoolean()) {
172         ViewAbstractModel::GetInstance()->SetTouchable(info[0]->ToBoolean());
173     }
174 }
175 
JsMonopolizeEvents(const JSCallbackInfo & info)176 void JSInteractableView::JsMonopolizeEvents(const JSCallbackInfo& info)
177 {
178     if (info[0]->IsBoolean()) {
179         ViewAbstractModel::GetInstance()->SetMonopolizeEvents(info[0]->ToBoolean());
180     } else {
181         ViewAbstractModel::GetInstance()->SetMonopolizeEvents(false);
182     }
183 }
184 
JsOnClick(const JSCallbackInfo & info)185 void JSInteractableView::JsOnClick(const JSCallbackInfo& info)
186 {
187     JSRef<JSVal> jsOnClickVal = info[0];
188     if (jsOnClickVal->IsUndefined() && IsDisableEventVersion()) {
189         ViewAbstractModel::GetInstance()->DisableOnClick();
190         return;
191     }
192     if (!jsOnClickVal->IsFunction()) {
193         return;
194     }
195     auto frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
196     WeakPtr<NG::FrameNode> weak = AceType::WeakClaim(frameNode);
197     auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(jsOnClickVal));
198     auto onTap = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc, node = weak](GestureEvent& info) {
199         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
200         ACE_SCORING_EVENT("onClick");
201         PipelineContext::SetCallBackNode(node);
202         func->Execute(info);
203 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
204         ReportClickEvent(node);
205 #endif
206     };
207     auto onClick = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc, node = weak](
208                        const ClickInfo* info) {
209         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
210         ACE_SCORING_EVENT("onClick");
211         PipelineContext::SetCallBackNode(node);
212         func->Execute(*info);
213 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
214         ReportClickEvent(node);
215 #endif
216     };
217 
218     double distanceThreshold = std::numeric_limits<double>::infinity();
219     if (info.Length() > 1 && info[1]->IsNumber()) {
220         distanceThreshold = info[1]->ToNumber<double>();
221     }
222     distanceThreshold = Dimension(distanceThreshold, DimensionUnit::VP).ConvertToPx();
223 
224     ViewAbstractModel::GetInstance()->SetOnClick(std::move(onTap), std::move(onClick), distanceThreshold);
225     CHECK_NULL_VOID(frameNode);
226     auto focusHub = frameNode->GetOrCreateFocusHub();
227     CHECK_NULL_VOID(focusHub);
228     focusHub->SetFocusable(true, false);
229 }
230 
SetFocusable(bool focusable)231 void JSInteractableView::SetFocusable(bool focusable)
232 {
233     ViewAbstractModel::GetInstance()->SetFocusable(focusable);
234 }
235 
SetFocusNode(bool isFocusNode)236 void JSInteractableView::SetFocusNode(bool isFocusNode)
237 {
238     ViewAbstractModel::GetInstance()->SetFocusNode(isFocusNode);
239 }
240 
JsOnAppear(const JSCallbackInfo & info)241 void JSInteractableView::JsOnAppear(const JSCallbackInfo& info)
242 {
243     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
244         ViewAbstractModel::GetInstance()->DisableOnAppear();
245         return;
246     }
247     if (info[0]->IsFunction()) {
248         RefPtr<JsFunction> jsOnAppearFunc =
249             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
250         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
251         auto onAppear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnAppearFunc), node = frameNode]() {
252             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
253             ACE_SCORING_EVENT("onAppear");
254             PipelineContext::SetCallBackNode(node);
255             func->Execute();
256         };
257         ViewAbstractModel::GetInstance()->SetOnAppear(std::move(onAppear));
258     }
259 }
260 
JsOnDisAppear(const JSCallbackInfo & info)261 void JSInteractableView::JsOnDisAppear(const JSCallbackInfo& info)
262 {
263     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
264         ViewAbstractModel::GetInstance()->DisableOnDisAppear();
265         return;
266     }
267     if (info[0]->IsFunction()) {
268         RefPtr<JsFunction> jsOnDisAppearFunc =
269             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
270         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
271         auto onDisappear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDisAppearFunc),
272                                node = frameNode]() {
273             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
274             ACE_SCORING_EVENT("onDisAppear");
275             PipelineContext::SetCallBackNode(node);
276             func->Execute();
277         };
278         ViewAbstractModel::GetInstance()->SetOnDisAppear(std::move(onDisappear));
279     }
280 }
281 
JsOnAttach(const JSCallbackInfo & info)282 void JSInteractableView::JsOnAttach(const JSCallbackInfo& info)
283 {
284     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
285         ViewAbstractModel::GetInstance()->DisableOnAttach();
286         return;
287     }
288     if (info[0]->IsFunction()) {
289         RefPtr<JsFunction> jsOnAttachFunc =
290             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
291         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
292         auto onAttach = [execCtx = info.GetExecutionContext(), func = std::move(jsOnAttachFunc), node = frameNode]() {
293             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
294             ACE_SCORING_EVENT("onAttach");
295             PipelineContext::SetCallBackNode(node);
296             func->Execute();
297         };
298         ViewAbstractModel::GetInstance()->SetOnAttach(std::move(onAttach));
299     }
300 }
301 
JsOnDetach(const JSCallbackInfo & info)302 void JSInteractableView::JsOnDetach(const JSCallbackInfo& info)
303 {
304     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
305         ViewAbstractModel::GetInstance()->DisableOnDetach();
306         return;
307     }
308     if (info[0]->IsFunction()) {
309         RefPtr<JsFunction> jsOnDetachFunc =
310             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
311         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
312         auto onDetach = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDetachFunc), node = frameNode]() {
313             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
314             ACE_SCORING_EVENT("onDetach");
315             PipelineContext::SetCallBackNode(node);
316             func->Execute();
317         };
318         ViewAbstractModel::GetInstance()->SetOnDetach(std::move(onDetach));
319     }
320 }
321 
JsOnAccessibility(const JSCallbackInfo & info)322 void JSInteractableView::JsOnAccessibility(const JSCallbackInfo& info)
323 {
324     if (!info[0]->IsFunction()) {
325         return;
326     }
327     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
328     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
329     auto onAccessibility = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
330                                const std::string& param) {
331         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
332         ACE_SCORING_EVENT("onAccessibility");
333         PipelineContext::SetCallBackNode(node);
334 
335         func->Execute({ "eventType" }, param);
336     };
337     ViewAbstractModel::GetInstance()->SetOnAccessibility(std::move(onAccessibility));
338 }
339 
JsCommonRemoteMessage(const JSCallbackInfo & info)340 void JSInteractableView::JsCommonRemoteMessage(const JSCallbackInfo& info)
341 {
342     if (info.Length() != 0 && info[0]->IsObject()) {
343         RemoteCallback remoteCallback;
344         JsRemoteMessage(info, remoteCallback);
345         ViewAbstractModel::GetInstance()->SetOnRemoteMessage(std::move(remoteCallback));
346     }
347 }
348 
JsRemoteMessage(const JSCallbackInfo & info,RemoteCallback & remoteCallback)349 void JSInteractableView::JsRemoteMessage(const JSCallbackInfo& info, RemoteCallback& remoteCallback)
350 {
351     if (!info[0]->IsObject()) {
352         return;
353     }
354 
355     auto eventCallback = GetRemoteMessageEventCallback(info);
356     remoteCallback = [func = std::move(eventCallback)](const BaseEventInfo* info) {
357         auto touchInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
358         if (touchInfo && touchInfo->GetType().compare("onClick") == 0) {
359             func();
360         }
361     };
362 }
363 
GetRemoteMessageEventCallback(const JSCallbackInfo & info)364 std::function<void()> JSInteractableView::GetRemoteMessageEventCallback(const JSCallbackInfo& info)
365 {
366     JSRef<JSVal> arg = info[0];
367     if (!arg->IsObject()) {
368         return []() {};
369     }
370     auto obj = JSRef<JSObject>::Cast(arg);
371     auto actionValue = obj->GetProperty("action");
372     std::string action;
373     if (actionValue->IsString()) {
374         action = actionValue->ToString();
375     }
376     auto abilityValue = obj->GetProperty("ability");
377     std::string ability;
378     if (abilityValue->IsString()) {
379         ability = abilityValue->ToString();
380     }
381     auto paramsObj = obj->GetProperty("params");
382     std::string params;
383     if (paramsObj->IsObject()) {
384         params = paramsObj->ToString();
385     }
386     auto eventCallback = [action, ability, params]() {
387         if (action.compare("message") == 0) {
388             // onCall
389         } else if (action.compare("route") == 0) {
390             // startAbility
391 #ifdef PLUGIN_COMPONENT_SUPPORTED
392             std::vector<std::string> strList;
393             SplitString(ability, '/', strList);
394             if (strList.size() <= 1) {
395                 return;
396             }
397             int32_t result = PluginManager::GetInstance().StartAbility(strList[0], strList[1], params);
398             if (result != 0) {
399                 LOGW("Failed to start the APP %{public}s.", ability.c_str());
400             }
401 #else
402             LOGW("Unsupported Windows and Mac platforms to start APP.");
403 #endif
404         }
405     };
406 
407     return eventCallback;
408 }
409 
410 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
ReportClickEvent(const WeakPtr<NG::FrameNode> & node,const std::string text)411 void JSInteractableView::ReportClickEvent(const WeakPtr<NG::FrameNode>& node, const std::string text)
412 {
413     if (UiSessionManager::GetInstance().GetClickEventRegistered()) {
414         auto data = JsonUtil::Create();
415         data->Put("event", "onClick");
416         std::string content = text;
417         if (!node.Invalid()) {
418             data->Put("id", node.GetRawPtr()->GetId());
419             auto children = node.GetRawPtr()->GetChildren();
420             if (!children.empty()) {
421                 node.GetRawPtr()->GetContainerComponentText(content);
422             }
423             data->Put("text", content.data());
424             data->Put("position", node.GetRawPtr()->GetGeometryNode()->GetFrameRect().ToString().data());
425         }
426         UiSessionManager::GetInstance().ReportClickEvent(data->ToString());
427     }
428 }
429 #endif
430 
SplitString(const std::string & str,char tag,std::vector<std::string> & strList)431 void JSInteractableView::SplitString(const std::string& str, char tag, std::vector<std::string>& strList)
432 {
433     std::string subStr;
434     for (size_t i = 0; i < str.length(); i++) {
435         if (tag == str[i]) {
436             if (!subStr.empty()) {
437                 strList.push_back(subStr);
438                 subStr.clear();
439             }
440         } else {
441             subStr.push_back(str[i]);
442         }
443     }
444     if (!subStr.empty()) {
445         strList.push_back(subStr);
446     }
447 }
448 } // namespace OHOS::Ace::Framework
449