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_xcomponent.h"
17
18 #include "base/log/ace_scoring_log.h"
19 #include "base/memory/referenced.h"
20 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
21 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
22 #include "bridge/declarative_frontend/jsview/js_xcomponent_controller.h"
23 #include "bridge/declarative_frontend/jsview/models/xcomponent_model_impl.h"
24 #include "core/components_ng/pattern/xcomponent/xcomponent_model.h"
25 #include "core/components_ng/pattern/xcomponent/xcomponent_model_ng.h"
26
27 namespace OHOS::Ace {
28 namespace {
ConvertToXComponentType(const std::string & type)29 XComponentType ConvertToXComponentType(const std::string& type)
30 {
31 if (type == "surface") {
32 return XComponentType::SURFACE;
33 }
34 if (type == "component") {
35 return XComponentType::COMPONENT;
36 }
37 LOGW("type: %{public}s is not valid, use 'surface' type as default", type.c_str());
38 return XComponentType::SURFACE;
39 }
40 } // namespace
41
42 std::unique_ptr<XComponentModel> XComponentModel::instance_ = nullptr;
43 std::mutex XComponentModel::mutex_;
44
GetInstance()45 XComponentModel* XComponentModel::GetInstance()
46 {
47 if (!instance_) {
48 std::lock_guard<std::mutex> lock(mutex_);
49 if (!instance_) {
50 #ifdef NG_BUILD
51 instance_.reset(new NG::XComponentModelNG());
52 #else
53 if (Container::IsCurrentUseNewPipeline()) {
54 instance_.reset(new NG::XComponentModelNG());
55 } else {
56 instance_.reset(new Framework::XComponentModelImpl());
57 }
58 #endif
59 }
60 }
61 return instance_.get();
62 }
63
64 } // namespace OHOS::Ace
65
66 namespace OHOS::Ace::Framework {
JSBind(BindingTarget globalObj)67 void JSXComponent::JSBind(BindingTarget globalObj)
68 {
69 JSClass<JSXComponent>::Declare("XComponent");
70 JSClass<JSXComponent>::StaticMethod("create", &JSXComponent::Create);
71 JSClass<JSXComponent>::StaticMethod("onLoad", &JSXComponent::JsOnLoad);
72 JSClass<JSXComponent>::StaticMethod("onDestroy", &JSXComponent::JsOnDestroy);
73
74 JSClass<JSXComponent>::StaticMethod("onAppear", &JSXComponent::OmitEvent);
75 JSClass<JSXComponent>::StaticMethod("onDisAppear", &JSXComponent::OmitEvent);
76 JSClass<JSXComponent>::StaticMethod("onTouch", &JSXComponent::OmitEvent);
77 JSClass<JSXComponent>::StaticMethod("onClick", &JSXComponent::OmitEvent);
78 JSClass<JSXComponent>::StaticMethod("onKeyEvent", &JSXComponent::OmitEvent);
79 JSClass<JSXComponent>::StaticMethod("onMouse", &JSXComponent::OmitEvent);
80 JSClass<JSXComponent>::StaticMethod("onHover", &JSXComponent::OmitEvent);
81 JSClass<JSXComponent>::StaticMethod("onFocus", &JSXComponent::OmitEvent);
82 JSClass<JSXComponent>::StaticMethod("onBlur", &JSXComponent::OmitEvent);
83
84 JSClass<JSXComponent>::StaticMethod("backgroundColor", &JSXComponent::JsBackgroundColor);
85 JSClass<JSXComponent>::StaticMethod("backgroundImage", &JSXComponent::OmitAttribute);
86 JSClass<JSXComponent>::StaticMethod("backgroundImageSize", &JSXComponent::OmitAttribute);
87 JSClass<JSXComponent>::StaticMethod("backgroundImagePosition", &JSXComponent::OmitAttribute);
88 JSClass<JSXComponent>::StaticMethod("opacity", &JSXComponent::JsOpacity);
89 JSClass<JSXComponent>::StaticMethod("blur", &JSXComponent::OmitAttribute);
90 JSClass<JSXComponent>::StaticMethod("backdropBlur", &JSXComponent::OmitAttribute);
91 JSClass<JSXComponent>::StaticMethod("grayscale", &JSXComponent::OmitAttribute);
92 JSClass<JSXComponent>::StaticMethod("brightness", &JSXComponent::OmitAttribute);
93 JSClass<JSXComponent>::StaticMethod("saturate", &JSXComponent::OmitAttribute);
94 JSClass<JSXComponent>::StaticMethod("contrast", &JSXComponent::OmitAttribute);
95 JSClass<JSXComponent>::StaticMethod("invert", &JSXComponent::OmitAttribute);
96 JSClass<JSXComponent>::StaticMethod("sepia", &JSXComponent::OmitAttribute);
97 JSClass<JSXComponent>::StaticMethod("hueRotate", &JSXComponent::OmitAttribute);
98 JSClass<JSXComponent>::StaticMethod("colorBlend", &JSXComponent::OmitAttribute);
99 JSClass<JSXComponent>::StaticMethod("sphericalEffect", &JSXComponent::OmitAttribute);
100 JSClass<JSXComponent>::StaticMethod("lightUpEffect", &JSXComponent::OmitAttribute);
101 JSClass<JSXComponent>::StaticMethod("pixelStretchEffect", &JSXComponent::OmitAttribute);
102 JSClass<JSXComponent>::StaticMethod("linearGradientBlur", &JSXComponent::OmitAttribute);
103
104 JSClass<JSXComponent>::InheritAndBind<JSViewAbstract>(globalObj);
105 }
106
Create(const JSCallbackInfo & info)107 void JSXComponent::Create(const JSCallbackInfo& info)
108 {
109 if (info.Length() < 1 || !info[0]->IsObject()) {
110 LOGI("xcomponent create error, info is invalid");
111 return;
112 }
113 auto paramObject = JSRef<JSObject>::Cast(info[0]);
114 auto id = paramObject->GetProperty("id");
115 if (!id->IsString()) {
116 LOGI("xcomponent create error, id is invalid");
117 return;
118 }
119
120 auto type = paramObject->GetProperty("type");
121 auto libraryname = paramObject->GetProperty("libraryname");
122 auto controllerObj = paramObject->GetProperty("controller");
123 RefPtr<XComponentController> xcomponentController = nullptr;
124 if (controllerObj->IsObject()) {
125 auto* jsXComponentController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSXComponentController>();
126 if (jsXComponentController) {
127 XComponentClient::GetInstance().AddControllerToJSXComponentControllersMap(
128 id->ToString(), jsXComponentController);
129 xcomponentController = jsXComponentController->GetController();
130 }
131 }
132 XComponentType xcomponentType = XComponentType::SURFACE;
133 if (type->IsString()) {
134 xcomponentType = ConvertToXComponentType(type->ToString());
135 } else if (type->IsNumber()) {
136 xcomponentType = static_cast<XComponentType>(type->ToNumber<int32_t>());
137 }
138 XComponentModel::GetInstance()->Create(
139 id->ToString(), xcomponentType, libraryname->ToString(), xcomponentController);
140
141 if (info.Length() > 1 && info[1]->IsString()) {
142 auto soPath = info[1]->ToString();
143 XComponentModel::GetInstance()->SetSoPath(soPath);
144 }
145 }
146
JsOnLoad(const JSCallbackInfo & args)147 void JSXComponent::JsOnLoad(const JSCallbackInfo& args)
148 {
149 if (args.Length() < 1 || !args[0]->IsFunction()) {
150 LOGE("The arg is wrong, it is supposed to have atleast 1 argument.");
151 return;
152 }
153 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
154 auto onLoad = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& xcomponentId) {
155 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
156 ACE_SCORING_EVENT("XComponent.onLoad");
157 std::vector<std::string> keys = { "load", xcomponentId };
158 func->ExecuteNew(keys, "");
159 };
160 XComponentModel::GetInstance()->SetOnLoad(std::move(onLoad));
161 }
162
JsOnDestroy(const JSCallbackInfo & args)163 void JSXComponent::JsOnDestroy(const JSCallbackInfo& args)
164 {
165 if (args.Length() < 1 || !args[0]->IsFunction()) {
166 LOGE("The arg is wrong, it is supposed to have atleast 1 argument.");
167 return;
168 }
169 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
170 auto onDestroy = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)]() {
171 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
172 ACE_SCORING_EVENT("XComponent.onDestroy");
173 std::vector<std::string> keys = { "destroy" };
174 func->Execute(keys, "");
175 };
176 XComponentModel::GetInstance()->SetOnDestroy(std::move(onDestroy));
177 }
178
JsBackgroundColor(const JSCallbackInfo & args)179 void JSXComponent::JsBackgroundColor(const JSCallbackInfo& args)
180 {
181 if (!XComponentModel::GetInstance()->IsTexture()) {
182 LOGW("not support backgroundColor attribute");
183 return;
184 }
185 JSViewAbstract::JsBackgroundColor(args);
186 }
187
JsOpacity(const JSCallbackInfo & args)188 void JSXComponent::JsOpacity(const JSCallbackInfo& args)
189 {
190 if (!XComponentModel::GetInstance()->IsTexture()) {
191 LOGW("not support opacity attribute");
192 return;
193 }
194 JSViewAbstract::JsOpacity(args);
195 }
196
OmitEvent(const JSCallbackInfo &)197 void JSXComponent::OmitEvent(const JSCallbackInfo& /*args*/)
198 {
199 LOGW("This event is omitted, please use apis of native_xcomponent instead");
200 }
201
OmitAttribute(const JSCallbackInfo &)202 void JSXComponent::OmitAttribute(const JSCallbackInfo& /* args */)
203 {
204 LOGW("This attribute is omitted.");
205 }
206 } // namespace OHOS::Ace::Framework
207