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_embedded_component.h"
17
18 #include <cstdint>
19 #include <functional>
20 #include <string>
21
22 #include "base/log/ace_scoring_log.h"
23 #include "base/log/log_wrapper.h"
24 #include "base/memory/ace_type.h"
25 #include "base/thread/task_executor.h"
26 #include "base/utils/utils.h"
27 #include "bridge/common/utils/engine_helper.h"
28 #include "bridge/declarative_frontend/engine/js_converter.h"
29 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
30 #include "bridge/declarative_frontend/engine/js_types.h"
31 #include "bridge/declarative_frontend/engine/jsi/jsi_ref.h"
32 #include "bridge/declarative_frontend/engine/jsi/jsi_types.h"
33 #include "bridge/declarative_frontend/jsview/js_ui_extension.h"
34 #include "bridge/declarative_frontend/jsview/js_utils.h"
35 #include "bridge/js_frontend/engine/jsi/js_value.h"
36 #include "core/common/container.h"
37 #include "core/common/container_scope.h"
38 #include "core/components_ng/pattern/ui_extension/session_wrapper.h"
39 #include "core/components_ng/pattern/ui_extension/ui_extension_model.h"
40 #include "core/components_ng/pattern/ui_extension/ui_extension_model_ng.h"
41 #include "frameworks/core/components_ng/base/view_abstract_model.h"
42
43 namespace OHOS::Ace::Framework {
44 const CalcDimension EMBEDDED_COMPONENT_MIN_WIDTH(10.0f, DimensionUnit::VP);
45 const CalcDimension EMBEDDED_COMPONENT_MIN_HEIGHT(10.0f, DimensionUnit::VP);
46
JSBind(BindingTarget globalObj)47 void JSEmbeddedComponent::JSBind(BindingTarget globalObj)
48 {
49 JSClass<JSEmbeddedComponent>::Declare("EmbeddedComponent");
50 MethodOptions opt = MethodOptions::NONE;
51 JSClass<JSEmbeddedComponent>::StaticMethod("create", &JSEmbeddedComponent::Create, opt);
52 JSClass<JSEmbeddedComponent>::StaticMethod("onTerminated", &JSEmbeddedComponent::OnTerminated);
53 JSClass<JSEmbeddedComponent>::StaticMethod("onError", &JSEmbeddedComponent::OnError);
54 JSClass<JSEmbeddedComponent>::StaticMethod("width", &JSEmbeddedComponent::JsWidth);
55 JSClass<JSEmbeddedComponent>::StaticMethod("height", &JSEmbeddedComponent::JsHeight);
56 JSClass<JSEmbeddedComponent>::StaticMethod("constraintSize", &JSEmbeddedComponent::JsConstraintSize);
57 JSClass<JSEmbeddedComponent>::StaticMethod("aspectRatio", &JSEmbeddedComponent::JsAspectRatio);
58 JSClass<JSEmbeddedComponent>::StaticMethod("layoutWeight", &JSEmbeddedComponent::JsLayoutWeight);
59 JSClass<JSEmbeddedComponent>::StaticMethod("flexBasis", &JSEmbeddedComponent::JsFlexBasis);
60 JSClass<JSEmbeddedComponent>::StaticMethod("flexGrow", &JSEmbeddedComponent::JsFlexGrow);
61 JSClass<JSEmbeddedComponent>::StaticMethod("flexShrink", &JSEmbeddedComponent::JsFlexShrink);
62 JSClass<JSEmbeddedComponent>::StaticMethod("opacity", &JSEmbeddedComponent::JsOpacity);
63 JSClass<JSEmbeddedComponent>::InheritAndBind<JSViewAbstract>(globalObj);
64 }
65
Create(const JSCallbackInfo & info)66 void JSEmbeddedComponent::Create(const JSCallbackInfo& info)
67 {
68 if (info.Length() < 1 || !info[0]->IsObject()) {
69 return;
70 }
71 auto wantObj = JSRef<JSObject>::Cast(info[0]);
72 RefPtr<OHOS::Ace::WantWrap> want = CreateWantWrapFromNapiValue(wantObj);
73
74 NG::SessionType sessionType = NG::SessionType::EMBEDDED_UI_EXTENSION;
75 if (info.Length() > 1 && info[1]->IsNumber()) {
76 sessionType = static_cast<NG::SessionType>(info[1]->ToNumber<int32_t>());
77 }
78
79 UIExtensionModel::GetInstance()->Create(want, sessionType);
80 ViewAbstractModel::GetInstance()->SetWidth(EMBEDDED_COMPONENT_MIN_WIDTH);
81 ViewAbstractModel::GetInstance()->SetHeight(EMBEDDED_COMPONENT_MIN_HEIGHT);
82 ViewAbstractModel::GetInstance()->SetMinWidth(EMBEDDED_COMPONENT_MIN_WIDTH);
83 ViewAbstractModel::GetInstance()->SetMinHeight(EMBEDDED_COMPONENT_MIN_HEIGHT);
84 }
85
OnTerminated(const JSCallbackInfo & info)86 void JSEmbeddedComponent::OnTerminated(const JSCallbackInfo& info)
87 {
88 if (!info[0]->IsFunction()) {
89 return;
90 }
91 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
92 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
93 auto instanceId = ContainerScope::CurrentId();
94 auto onTerminated = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode](
95 int32_t code, const RefPtr<WantWrap>& wantWrap) {
96 ContainerScope scope(instanceId);
97 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
98 ACE_SCORING_EVENT("EmbeddedComponent.onTerminated");
99 auto pipelineContext = PipelineContext::GetCurrentContext();
100 CHECK_NULL_VOID(pipelineContext);
101 pipelineContext->UpdateCurrentActiveNode(node);
102 auto engine = EngineHelper::GetCurrentEngine();
103 CHECK_NULL_VOID(engine);
104 NativeEngine* nativeEngine = engine->GetNativeEngine();
105 CHECK_NULL_VOID(nativeEngine);
106 JSRef<JSObject> obj = JSRef<JSObject>::New();
107 obj->SetProperty<int32_t>("code", code);
108 if (wantWrap) {
109 auto nativeWant =
110 WantWrap::ConvertToNativeValue(wantWrap->GetWant(), reinterpret_cast<napi_env>(nativeEngine));
111 auto wantJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWant);
112 obj->SetPropertyObject("want", wantJSVal);
113 }
114 auto returnValue = JSRef<JSVal>::Cast(obj);
115 func->ExecuteJS(1, &returnValue);
116 };
117 UIExtensionModel::GetInstance()->SetOnTerminated(std::move(onTerminated));
118 }
119
OnError(const JSCallbackInfo & info)120 void JSEmbeddedComponent::OnError(const JSCallbackInfo& info)
121 {
122 if (!info[0]->IsFunction()) {
123 return;
124 }
125 auto frameNode = AceType::Claim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
126 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
127 auto instanceId = ContainerScope::CurrentId();
128 auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode](
129 int32_t code, const std::string& name, const std::string& message) {
130 ContainerScope scope(instanceId);
131 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
132 ACE_SCORING_EVENT("EmbeddedComponent.onError");
133 auto pipelineContext = PipelineContext::GetCurrentContext();
134 CHECK_NULL_VOID(pipelineContext);
135 pipelineContext->UpdateCurrentActiveNode(node);
136 JSRef<JSObject> obj = JSRef<JSObject>::New();
137 obj->SetProperty<int32_t>("code", code);
138 obj->SetProperty<std::string>("name", name);
139 obj->SetProperty<std::string>("message", message);
140 auto returnValue = JSRef<JSVal>::Cast(obj);
141 func->ExecuteJS(FUNC_ARGC_1, &returnValue);
142 };
143 UIExtensionModel::GetInstance()->SetOnError(std::move(onError));
144 }
145
JsWidth(const JSCallbackInfo & info)146 void JSEmbeddedComponent::JsWidth(const JSCallbackInfo& info)
147 {
148 if (info[0]->IsUndefined()) {
149 return;
150 }
151
152 CalcDimension value;
153 if (JSViewAbstract::ParseJsDimensionVpNG(info[0], value)) {
154 ViewAbstractModel::GetInstance()->SetWidth(value);
155 }
156 }
157
JsHeight(const JSCallbackInfo & info)158 void JSEmbeddedComponent::JsHeight(const JSCallbackInfo& info)
159 {
160 if (info[0]->IsUndefined()) {
161 return;
162 }
163
164 CalcDimension value;
165 if (JSViewAbstract::ParseJsDimensionVpNG(info[0], value)) {
166 ViewAbstractModel::GetInstance()->SetHeight(value);
167 }
168 }
169 } // namespace OHOS::Ace::Framework
170