• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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