1 /*
2  * Copyright (c) 2021-2023 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_plugin.h"
17 
18 #include "base/geometry/dimension.h"
19 #include "base/log/ace_scoring_log.h"
20 #include "base/log/log_wrapper.h"
21 #include "bridge/declarative_frontend/jsview/models/plugin_model_impl.h"
22 #include "core/components/common/properties/clip_path.h"
23 #include "core/components_ng/base/view_stack_processor.h"
24 #include "core/components_ng/pattern/plugin/plugin_model.h"
25 #include "core/components_ng/pattern/plugin/plugin_model_ng.h"
26 #include "core/components_ng/pattern/plugin/plugin_pattern.h"
27 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
28 #include "frameworks/core/components/box/box_component.h"
29 #include "frameworks/core/components/plugin/plugin_component.h"
30 
31 namespace OHOS::Ace {
32 std::unique_ptr<PluginModel> PluginModel::instance_;
33 std::mutex PluginModel::mutex_;
34 
GetInstance()35 PluginModel* PluginModel::GetInstance()
36 {
37     if (!instance_) {
38         std::lock_guard<std::mutex> lock(mutex_);
39         if (!instance_) {
40 #ifdef NG_BUILD
41             instance_.reset(new NG::PluginModelNG());
42 #else
43             if (Container::IsCurrentUseNewPipeline()) {
44                 instance_.reset(new NG::PluginModelNG());
45             } else {
46                 instance_.reset(new Framework::PluginModelImpl());
47             }
48 #endif
49         }
50     }
51     return instance_.get();
52 }
53 } // namespace OHOS::Ace
54 namespace OHOS::Ace::Framework {
Create(const JSCallbackInfo & info)55 void JSPlugin::Create(const JSCallbackInfo& info)
56 {
57     if (!info[0]->IsObject()) {
58         return;
59     }
60 
61     // Parse template
62     RequestPluginInfo pluginInfo;
63     auto obj = JSRef<JSObject>::Cast(info[0]);
64     auto templateObj = obj->GetProperty("template");
65     if (templateObj->IsObject()) {
66         auto jstemplateObj = JSRef<JSObject>::Cast(templateObj);
67         auto sourceVal = jstemplateObj->GetProperty("source");
68         if (sourceVal->IsString()) {
69             pluginInfo.pluginName = sourceVal->ToString();
70         }
71         auto abilityVal = jstemplateObj->GetProperty("ability");
72         if (!abilityVal->IsEmpty() && abilityVal->IsString()) {
73             pluginInfo.bundleName = abilityVal->ToString();
74         }
75 
76         auto bundleValue = jstemplateObj->GetProperty("bundleName");
77         if (!bundleValue->IsEmpty() && bundleValue->IsString()) {
78             pluginInfo.bundleName = bundleValue->ToString();
79         }
80     }
81     if (pluginInfo.bundleName.size() > PATH_MAX || pluginInfo.pluginName.size() > PATH_MAX) {
82         return;
83     }
84     // Parse data
85     auto dataValue = obj->GetProperty("data");
86 
87     PluginModel::GetInstance()->Create(pluginInfo);
88     if (dataValue->IsObject()) {
89         PluginModel::GetInstance()->SetData(dataValue->ToString());
90     }
91 }
92 
JsSize(const JSCallbackInfo & info)93 void JSPlugin::JsSize(const JSCallbackInfo& info)
94 {
95     if (!info[0]->IsObject()) {
96         return;
97     }
98 
99     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
100     JSRef<JSVal> widthValue = sizeObj->GetProperty("width");
101     CalcDimension width = 0.0_vp;
102     if (!ParseJsDimensionVp(widthValue, width)) {
103         return;
104     }
105     JSRef<JSVal> heightValue = sizeObj->GetProperty("height");
106     CalcDimension height = 0.0_vp;
107     if (!ParseJsDimensionVp(heightValue, height)) {
108         return;
109     }
110     PluginModel::GetInstance()->SetPluginSize(width.IsValid() ? width : 0.0_vp, height.IsValid() ? height : 0.0_vp);
111 }
112 
JsWidth(const JSCallbackInfo & info)113 void JSPlugin::JsWidth(const JSCallbackInfo& info)
114 {
115     CalcDimension value;
116     if (!ParseJsDimensionVp(info[0], value)) {
117         return;
118     }
119 
120     if (LessNotEqual(value.Value(), 0.0)) {
121         value.SetValue(0.0);
122     }
123 
124     PluginModel::GetInstance()->SetWidth(value.IsValid() ? value : 0.0_vp);
125 }
126 
JsHeight(const JSCallbackInfo & info)127 void JSPlugin::JsHeight(const JSCallbackInfo& info)
128 {
129     CalcDimension value;
130     if (!ParseJsDimensionVp(info[0], value)) {
131         return;
132     }
133 
134     if (LessNotEqual(value.Value(), 0.0)) {
135         value.SetValue(0.0);
136     }
137 
138     PluginModel::GetInstance()->SetHeight(value.IsValid() ? value : 0.0_vp);
139 }
140 
JsOnComplete(const JSCallbackInfo & info)141 void JSPlugin::JsOnComplete(const JSCallbackInfo& info)
142 {
143 #if defined(PLUGIN_COMPONENT_SUPPORTED)
144     if (info[0]->IsFunction()) {
145         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
146         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
147         auto OnComplete = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
148                                 const std::string& param) {
149             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
150             ACE_SCORING_EVENT("Plugin.OnComplete");
151             PipelineContext::SetCallBackNode(node);
152             func->Execute();
153         };
154         PluginModel::GetInstance()->SetOnComplete(std::move(OnComplete));
155     }
156 #endif
157 }
158 
JsOnError(const JSCallbackInfo & info)159 void JSPlugin::JsOnError(const JSCallbackInfo& info)
160 {
161 #if defined(PLUGIN_COMPONENT_SUPPORTED)
162     if (info[0]->IsFunction()) {
163         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
164         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
165         auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
166                             const std::string& param) {
167             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
168             ACE_SCORING_EVENT("Plugin.OnComplete");
169             std::vector<std::string> keys = { "errcode", "msg" };
170             PipelineContext::SetCallBackNode(node);
171             func->Execute(keys, param);
172         };
173         PluginModel::GetInstance()->SetOnError(std::move(onError));
174     }
175 #endif
176 }
177 
JSBind(BindingTarget globalObj)178 void JSPlugin::JSBind(BindingTarget globalObj)
179 {
180     JSClass<JSPlugin>::Declare("PluginComponent");
181     MethodOptions opt = MethodOptions::NONE;
182     JSClass<JSPlugin>::StaticMethod("create", &JSPlugin::Create, opt);
183     JSClass<JSPlugin>::StaticMethod("size", &JSPlugin::JsSize, opt);
184     JSClass<JSPlugin>::StaticMethod("width", &JSPlugin::JsWidth);
185     JSClass<JSPlugin>::StaticMethod("height", &JSPlugin::JsHeight);
186     JSClass<JSPlugin>::StaticMethod("onComplete", &JSPlugin::JsOnComplete);
187     JSClass<JSPlugin>::StaticMethod("onError", &JSPlugin::JsOnError);
188     JSClass<JSPlugin>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
189     JSClass<JSPlugin>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
190     JSClass<JSPlugin>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
191     JSClass<JSPlugin>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
192     JSClass<JSPlugin>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
193     JSClass<JSPlugin>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
194     JSClass<JSPlugin>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
195     JSClass<JSPlugin>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
196 
197     JSClass<JSPlugin>::InheritAndBind<JSViewAbstract>(globalObj);
198 }
199 } // namespace OHOS::Ace::Framework
200