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/declarative_frontend/jsview/js_form_menu_item.h"
17 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
18 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
19 #endif
20 
21 #include "want.h"
22 
23 #include "base/log/ace_scoring_log.h"
24 #include "base/log/log_wrapper.h"
25 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
26 #include "bridge/declarative_frontend/engine/js_types.h"
27 #include "bridge/declarative_frontend/jsview/js_utils.h"
28 #include "bridge/declarative_frontend/jsview/models/form_model_impl.h"
29 #include "bridge/declarative_frontend/jsview/models/menu_item_model_impl.h"
30 #include "bridge/declarative_frontend/jsview/js_menu_item.h"
31 #include "bridge/declarative_frontend/view_stack_processor.h"
32 #include "core/components_ng/base/view_abstract.h"
33 #include "core/components_ng/base/view_abstract_model.h"
34 #include "core/components_ng/base/view_stack_model.h"
35 #include "core/components_ng/base/view_stack_processor.h"
36 #include "core/components_ng/pattern/form/form_model_ng.h"
37 #include "core/components_ng/pattern/menu/menu_item/menu_item_model.h"
38 #include "core/components_ng/pattern/menu/menu_item/menu_item_model_ng.h"
39 
40 namespace OHOS::Ace::Framework {
41 namespace {
42 constexpr int NUM_WANT_1 = 0;
43 constexpr int NUM_ID_2 = 1;
44 constexpr int NUM_DATA_3 = 2;
45 constexpr int NUM_FUN_4 = 3;
46 constexpr int NUM_CALLBACKNUM = 2;
47 }
48 
49 
JSBind(BindingTarget globalObj)50 void JSFormMenuItem::JSBind(BindingTarget globalObj)
51 {
52     JSClass<JSFormMenuItem>::Declare("FormMenuItem");
53     MethodOptions opt = MethodOptions::NONE;
54     JSClass<JSFormMenuItem>::StaticMethod("create", &JSMenuItem::Create, opt);
55     JSClass<JSFormMenuItem>::StaticMethod("onRegClick", &JSFormMenuItem::JsOnRegClick);
56     JSClass<JSFormMenuItem>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
57     JSClass<JSFormMenuItem>::InheritAndBind<JSViewAbstract>(globalObj);
58 }
59 
RequestPublishFormWithSnapshot(JSRef<JSVal> wantValue,const std::string & formBindingDataStr,RefPtr<JsFunction> jsCBFunc)60 void JSFormMenuItem::RequestPublishFormWithSnapshot(JSRef<JSVal> wantValue,
61     const std::string& formBindingDataStr, RefPtr<JsFunction> jsCBFunc)
62 {
63     RefPtr<WantWrap> wantWrap = CreateWantWrapFromNapiValue(wantValue);
64     if (!wantWrap) {
65         TAG_LOGE(AceLogTag::ACE_FORM, "onTap wantWrap is NULL.");
66         return;
67     }
68 
69     int64_t formId = 0;
70     AAFwk::Want& want = const_cast<AAFwk::Want&>(wantWrap->GetWant());
71     if (!want.HasParameter("ohos.extra.param.key.add_form_to_host_snapshot") ||
72         !want.HasParameter("ohos.extra.param.key.add_form_to_host_width") ||
73         !want.HasParameter("ohos.extra.param.key.add_form_to_host_height") ||
74         !want.HasParameter("ohos.extra.param.key.add_form_to_host_screenx") ||
75         !want.HasParameter("ohos.extra.param.key.add_form_to_host_screeny")) {
76         TAG_LOGE(AceLogTag::ACE_FORM, "want has no component snapshot info");
77         return;
78     }
79 
80     std::string errMsg;
81     int32_t errCode = FormModel::GetInstance()->RequestPublishFormWithSnapshot(want, formBindingDataStr, formId,
82                                                                                errMsg);
83     if (!jsCBFunc) {
84         TAG_LOGE(AceLogTag::ACE_FORM, "jsCBFunc is null");
85         return;
86     }
87 
88     JSRef<JSVal> params[NUM_CALLBACKNUM];
89     JSRef<JSObject> errObj = JSRef<JSObject>::New();
90     errObj->SetProperty<int32_t>("code", errCode);
91     errObj->SetProperty<std::string>("message", errMsg);
92     params[0] = errObj;
93     params[1] = JSRef<JSVal>::Make(ToJSValue(std::to_string(formId)));
94     jsCBFunc->ExecuteJS(NUM_CALLBACKNUM, params);
95 }
96 
JsOnRegClick(const JSCallbackInfo & info)97 void JSFormMenuItem::JsOnRegClick(const JSCallbackInfo& info)
98 {
99     bool retFlag;
100     OnClickParameterCheck(info, retFlag);
101     if (retFlag) {
102         return;
103     }
104 
105     std::string compId;
106     JSViewAbstract::ParseJsString(info[NUM_ID_2], compId);
107     if (compId.empty()) {
108         TAG_LOGE(AceLogTag::ACE_FORM, "JsOnClick compId is empty.Input parameter componentId check failed.");
109         return;
110     }
111 
112     std::string formBindingDataStr;
113     JSViewAbstract::ParseJsString(info[NUM_DATA_3], formBindingDataStr);
114     if (formBindingDataStr.empty()) {
115         TAG_LOGW(AceLogTag::ACE_FORM, "JsOnClick formBindingDataStr is empty");
116     }
117 
118     RefPtr<JsFunction> jsCallBackFunc = nullptr;
119     if (!info[NUM_FUN_4]->IsUndefined() && info[NUM_FUN_4]->IsFunction()) {
120         jsCallBackFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[NUM_FUN_4]));
121     }
122 
123     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
124 
125     auto onTap = [execCtx = info.GetExecutionContext(),  node = targetNode,
126         jsCBFunc = std::move(jsCallBackFunc), want = info[NUM_WANT_1], formBindingDataStr] (GestureEvent& event) {
127         JSRef<JSVal> wantValue = JSRef<JSVal>::Cast(want);
128         if (wantValue->IsNull()) {
129             TAG_LOGE(AceLogTag::ACE_FORM, "JsOnClick wantValue is null");
130             return;
131         }
132         TAG_LOGI(AceLogTag::ACE_FORM, "JsOnClick ontap");
133         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
134         ACE_SCORING_EVENT("onTap");
135         RequestPublishFormWithSnapshot(wantValue, formBindingDataStr, jsCBFunc);
136 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
137         JSInteractableView::ReportClickEvent(node);
138 #endif
139     };
140 
141     auto onClick = [execCtx = info.GetExecutionContext(), node = targetNode,
142         jsCBFunc = std::move(jsCallBackFunc), want = info[NUM_WANT_1], formBindingDataStr]
143         (const ClickInfo* event) {
144         JSRef<JSVal> wantValue = JSRef<JSVal>::Cast(want);
145         if (wantValue->IsNull()) {
146             TAG_LOGE(AceLogTag::ACE_FORM, "JsOnClick wantValue is null");
147             return;
148         }
149         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
150         ACE_SCORING_EVENT("onClick");
151         PipelineContext::SetCallBackNode(node);
152         RequestPublishFormWithSnapshot(wantValue, formBindingDataStr, jsCBFunc);
153 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
154         JSInteractableView::ReportClickEvent(node);
155 #endif
156     };
157     ViewAbstractModel::GetInstance()->SetOnClick(std::move(onTap), std::move(onClick));
158 }
159 
OnClickParameterCheck(const JSCallbackInfo & info,bool & retFlag)160 void JSFormMenuItem::OnClickParameterCheck(const JSCallbackInfo& info, bool& retFlag)
161 {
162     retFlag = true;
163 
164     if (info[NUM_WANT_1]->IsUndefined() || !info[NUM_WANT_1]->IsObject() || info[NUM_ID_2]->IsUndefined() ||
165         !info[NUM_ID_2]->IsString()) {
166         TAG_LOGE(AceLogTag::ACE_FORM, "OnClickParameterCheck bad parameter info[1] and info[2]");
167         return;
168     }
169     retFlag = false;
170 }
171 } // namespace OHOS::Ace::Framework