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/js_frontend/engine/quickjs/qjs_xcomponent_bridge.h"
17
18 #include "base/utils/string_utils.h"
19 #include "frameworks/bridge/common/utils/utils.h"
20 #include "frameworks/bridge/js_frontend/engine/quickjs/qjs_engine.h"
21 #include "frameworks/bridge/js_frontend/js_command.h"
22 #include "frameworks/core/common/ace_view.h"
23 #include "frameworks/core/common/container.h"
24
25 namespace OHOS::Ace::Framework {
QjsXComponentBridge()26 QjsXComponentBridge::QjsXComponentBridge()
27 {
28 nativeXComponentImpl_ = AceType::MakeRefPtr<NativeXComponentImpl>();
29 nativeXComponent_ = new OH_NativeXComponent(AceType::RawPtr(nativeXComponentImpl_));
30 renderContext_ = JS_NULL;
31 }
32
~QjsXComponentBridge()33 QjsXComponentBridge::~QjsXComponentBridge()
34 {
35 if (nativeXComponent_) {
36 delete nativeXComponent_;
37 nativeXComponent_ = nullptr;
38 }
39 }
40
HandleContext(JSContext * ctx,NodeId id,const std::string & args)41 void QjsXComponentBridge::HandleContext(JSContext* ctx, NodeId id, const std::string& args)
42 {
43 if (hasPluginLoaded_) {
44 return;
45 }
46
47 auto engine = static_cast<QjsEngineInstance*>(JS_GetContextOpaque(ctx));
48 if (engine == nullptr) {
49 LOGE("QjsXComponentBridge::HandleJsContext, engine is null.");
50 return;
51 }
52
53 auto page = engine->GetRunningPage();
54 if (!page) {
55 LOGE("QjsXComponentBridge page is null.");
56 return;
57 }
58 auto domXcomponent = AceType::DynamicCast<DOMXComponent>(page->GetDomDocument()->GetDOMNodeById(id));
59 if (!domXcomponent) {
60 LOGE("QjsXComponentBridge domXcomponent is null.");
61 return;
62 }
63 auto xcomponent = AceType::DynamicCast<XComponentComponent>(domXcomponent->GetSpecializedComponent());
64 if (!xcomponent) {
65 LOGE("QjsXComponentBridge xcomponent is null.");
66 return;
67 }
68
69 auto container = Container::Current();
70 if (!container) {
71 LOGE("QjsXComponentBridge Current container null");
72 return;
73 }
74 auto nativeView = static_cast<AceView*>(container->GetView());
75 if (!nativeView) {
76 LOGE("QjsXComponentBridge nativeView null");
77 return;
78 }
79
80 void* nativeWindow = nullptr;
81 #ifdef OHOS_STANDARD_SYSTEM
82 nativeWindow = const_cast<void*>(xcomponent->GetNativeWindow());
83 #else
84 auto textureId = static_cast<int64_t>(xcomponent->GetTextureId());
85 nativeWindow = const_cast<void*>(nativeView->GetNativeWindowById(textureId));
86 #endif
87 if (!nativeWindow) {
88 LOGE("QjsXComponentBridge::HandleJsContext nativeWindow invalid");
89 return;
90 }
91
92 nativeXComponentImpl_->SetSurface(nativeWindow);
93 nativeXComponentImpl_->SetXComponentId(xcomponent->GetId());
94
95 #ifdef XCOMPONENT_SUPPORTED
96 auto nativeEngine = static_cast<QuickJSNativeEngine*>(engine->GetQuickJSNativeEngine());
97 if (nativeEngine == nullptr) {
98 LOGE("nativeEngine is null");
99 return;
100 }
101
102 renderContext_ = nativeEngine->LoadModuleByName(xcomponent->GetLibraryName(), true,
103 args, OH_NATIVE_XCOMPONENT_OBJ,
104 reinterpret_cast<void*>(nativeXComponent_));
105
106 auto delegate = engine->GetDelegate();
107 if (delegate == nullptr) {
108 LOGE("delegate is null.");
109 return;
110 }
111 auto task = [weak = WeakClaim(this), xcomponent]() {
112 auto pool = xcomponent->GetTaskPool();
113 if (!pool) {
114 return;
115 }
116 auto bridge = weak.Upgrade();
117 if (bridge) {
118 pool->NativeXComponentInit(bridge->nativeXComponent_,
119 AceType::WeakClaim(AceType::RawPtr(bridge->nativeXComponentImpl_)));
120 }
121 };
122 delegate->PostSyncTaskToPage(task);
123 #endif
124 hasPluginLoaded_ = true;
125 return;
126 }
127
JsGetXComponentSurfaceId(JSContext * ctx,NodeId nodeId)128 JSValue QjsXComponentBridge::JsGetXComponentSurfaceId(JSContext* ctx, NodeId nodeId)
129 {
130 #ifdef XCOMPONENT_SUPPORTED
131 auto instance = static_cast<QjsEngineInstance*>(JS_GetContextOpaque(ctx));
132 if (instance == nullptr) {
133 LOGE("JsGetXComponentSurfaceId instance is null");
134 return JS_NULL;
135 }
136 auto page = instance->GetRunningPage();
137 if (!page) {
138 LOGE("JsGetXComponentSurfaceId page is null");
139 return JS_NULL;
140 }
141
142 std::string surfaceId = "";
143 auto task = [nodeId, page, &surfaceId]() {
144 auto domDoc = page->GetDomDocument();
145 if (!domDoc) {
146 return;
147 }
148 auto domXComponent = AceType::DynamicCast<DOMXComponent>(domDoc->GetDOMNodeById(nodeId));
149 if (!domXComponent) {
150 return;
151 }
152 surfaceId = domXComponent->GetSurfaceId();
153 };
154
155 auto delegate = instance->GetDelegate();
156 if (!delegate) {
157 LOGE("JsGetXComponentSurfaceId delegate is null");
158 return JS_NULL;
159 }
160 delegate->PostSyncTaskToPage(task);
161 JSValue result = JS_NewString(ctx, surfaceId.c_str());
162 return result;
163 #else
164 return JS_NULL;
165 #endif
166 }
167
JsSetXComponentSurfaceSize(JSContext * ctx,const std::string & args,NodeId nodeId)168 void QjsXComponentBridge::JsSetXComponentSurfaceSize(JSContext* ctx, const std::string& args, NodeId nodeId)
169 {
170 #ifdef XCOMPONENT_SUPPORTED
171 auto instance = static_cast<QjsEngineInstance*>(JS_GetContextOpaque(ctx));
172 if (instance == nullptr) {
173 LOGE("JsSetXComponentSurfaceSize instance is null");
174 return;
175 }
176 auto page = instance->GetRunningPage();
177 if (!page) {
178 LOGE("JsSetXComponentSurfaceSize page is null");
179 return;
180 }
181
182 auto task = [nodeId, page, args]() {
183 auto domDoc = page->GetDomDocument();
184 if (!domDoc) {
185 return;
186 }
187 auto domXComponent = AceType::DynamicCast<DOMXComponent>(domDoc->GetDOMNodeById(nodeId));
188 if (!domXComponent) {
189 return;
190 }
191
192 std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(args);
193 if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() < 1) {
194 LOGE("JsSetXComponentSurfaceSize failed. parse args error");
195 return;
196 }
197 std::unique_ptr<JsonValue> surfaceSizePara = argsValue->GetArrayItem(0);
198 uint32_t surfaceWidth = surfaceSizePara->GetUInt("surfaceWidth", 0);
199 uint32_t surfaceHeight = surfaceSizePara->GetUInt("surfaceHeight", 0);
200 domXComponent->SetSurfaceSize(surfaceWidth, surfaceHeight);
201 };
202
203 auto delegate = instance->GetDelegate();
204 if (!delegate) {
205 LOGE("JsSetXComponentSurfaceSize delegate is null");
206 return;
207 }
208 delegate->PostSyncTaskToPage(task);
209 #endif
210 }
211 } // namespace OHOS::Ace::Framework