• 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 <memory>
17 
18 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_xcomponent_bridge.h"
19 
20 #include "base/utils/string_utils.h"
21 #include "frameworks/bridge/common/utils/utils.h"
22 #include "frameworks/bridge/js_frontend/engine/jsi/ark_js_value.h"
23 #include "frameworks/bridge/js_frontend/js_command.h"
24 #include "frameworks/core/common/ace_view.h"
25 #include "frameworks/core/common/container.h"
26 
27 namespace OHOS::Ace::Framework {
JsiXComponentBridge()28 JsiXComponentBridge::JsiXComponentBridge()
29 {
30     nativeXcomponentImpl_ = AceType::MakeRefPtr<NativeXComponentImpl>();
31     nativeXComponent_ = new OH_NativeXComponent(AceType::RawPtr(nativeXcomponentImpl_));
32 }
33 
~JsiXComponentBridge()34 JsiXComponentBridge::~JsiXComponentBridge()
35 {
36     if (nativeXComponent_) {
37         delete nativeXComponent_;
38         nativeXComponent_ = nullptr;
39     }
40     // render context must be release on js thread.
41     auto currentContainer = Container::Current();
42     if (currentContainer) {
43         auto taskExecutor = currentContainer->GetTaskExecutor();
44         if (taskExecutor) {
45             taskExecutor->PostTask([ renderContext = std::move(renderContext_) ] () mutable {
46                 renderContext.reset();
47             },
48             TaskExecutor::TaskType::JS);
49         }
50     }
51 }
52 
HandleContext(const shared_ptr<JsRuntime> & runtime,NodeId id,const std::string & args)53 void JsiXComponentBridge::HandleContext(const shared_ptr<JsRuntime>& runtime, NodeId id, const std::string& args)
54 {
55     if (hasPluginLoaded_) {
56         return;
57     }
58 
59     if (!runtime) {
60         LOGE("Runtime is null");
61         return;
62     }
63 
64     auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
65     auto page = engineInstance->GetRunningPage();
66     if (!page) {
67         LOGE("JsiXComponentBridge page is null.");
68         return;
69     }
70     auto domXcomponent = AceType::DynamicCast<DOMXComponent>(page->GetDomDocument()->GetDOMNodeById(id));
71     if (!domXcomponent) {
72         LOGE("JsiXComponentBridge domXcomponent is null.");
73         return;
74     }
75     auto xcomponent = AceType::DynamicCast<XComponentComponent>(domXcomponent->GetSpecializedComponent());
76     if (!xcomponent) {
77         LOGE("JsiXComponentBridge xcomponent is null.");
78         return;
79     }
80 
81     auto container = Container::Current();
82     if (!container) {
83         LOGE("JsiXComponentBridge Current container null");
84         return;
85     }
86     auto nativeView = static_cast<AceView*>(container->GetView());
87     if (!nativeView) {
88         LOGE("JsiXComponentBridge nativeView null");
89         return;
90     }
91 
92     void* nativeWindow = nullptr;
93 #ifdef OHOS_STANDARD_SYSTEM
94     nativeWindow = const_cast<void*>(xcomponent->GetNativeWindow());
95 #else
96     auto textureId = static_cast<int64_t>(xcomponent->GetTextureId());
97     nativeWindow = const_cast<void*>(nativeView->GetNativeWindowById(textureId));
98 #endif
99     if (!nativeWindow) {
100         LOGE("JsiXComponentBridge::HandleJsContext nativeWindow invalid");
101         return;
102     }
103     nativeXcomponentImpl_->SetSurface(nativeWindow);
104     nativeXcomponentImpl_->SetXComponentId(xcomponent->GetId());
105 
106     auto nativeEngine = static_cast<ArkNativeEngine*>(engineInstance->GetNativeEngine());
107     if (!nativeEngine) {
108         LOGE("NativeEngine is null");
109         return;
110     }
111 
112     auto arkObjectRef = nativeEngine->LoadModuleByName(xcomponent->GetLibraryName(), true,
113                                                        args, OH_NATIVE_XCOMPONENT_OBJ,
114                                                        reinterpret_cast<void*>(nativeXComponent_));
115 
116     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
117     if (arkObjectRef.IsEmpty() || pandaRuntime->HasPendingException()) {
118         LOGE("LoadModuleByName failed.");
119         return;
120     }
121     renderContext_ = runtime->NewObject();
122     auto renderContext = std::static_pointer_cast<ArkJSValue>(renderContext_);
123     LocalScope scope(pandaRuntime->GetEcmaVm());
124     Local<ObjectRef> obj = arkObjectRef->ToObject(pandaRuntime->GetEcmaVm());
125     if (obj.IsEmpty() || pandaRuntime->HasPendingException()) {
126         LOGE("Get local object failed.");
127         renderContext_.reset();
128         return;
129     }
130     renderContext->SetValue(pandaRuntime, obj);
131 
132     auto task = [weak = WeakClaim(this), xcomponent]() {
133         auto pool = xcomponent->GetTaskPool();
134         if (!pool) {
135             return;
136         }
137         auto bridge = weak.Upgrade();
138         if (bridge) {
139             pool->NativeXComponentInit(
140                 bridge->nativeXComponent_,
141                 AceType::WeakClaim(AceType::RawPtr(bridge->nativeXcomponentImpl_)));
142         }
143     };
144 
145     auto delegate = engineInstance->GetFrontendDelegate();
146     if (!delegate) {
147         LOGE("Delegate is null");
148         return;
149     }
150     delegate->PostSyncTaskToPage(task);
151 
152     hasPluginLoaded_ = true;
153     return;
154 }
155 
JsGetXComponentSurfaceId(const shared_ptr<JsRuntime> & runtime,NodeId nodeId)156 shared_ptr<JsValue> JsiXComponentBridge::JsGetXComponentSurfaceId(const shared_ptr<JsRuntime>& runtime, NodeId nodeId)
157 {
158     if (!runtime) {
159         LOGE("JsGetXComponentSurfaceId failed. runtime is null.");
160         return nullptr;
161     }
162     auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
163     if (!engine) {
164         LOGE("JsGetXComponentSurfaceId failed. engine is null.");
165         return runtime->NewUndefined();
166     }
167     auto page = engine->GetRunningPage();
168     if (!page) {
169         LOGE("JsGetXComponentSurfaceId failed. page is null.");
170         return runtime->NewUndefined();
171     }
172     std::string surfaceId = "";
173     auto task = [nodeId, page, &surfaceId]() {
174         auto domDoc = page->GetDomDocument();
175         if (!domDoc) {
176             return;
177         }
178         auto domXComponent = AceType::DynamicCast<DOMXComponent>(domDoc->GetDOMNodeById(nodeId));
179         if (!domXComponent) {
180             return;
181         }
182         surfaceId = domXComponent->GetSurfaceId();
183     };
184     auto delegate = engine->GetFrontendDelegate();
185     if (!delegate) {
186         LOGE("JsGetXComponentSurfaceId failed. delegate is null.");
187         return runtime->NewUndefined();
188     }
189     delegate->PostSyncTaskToPage(task);
190     return runtime->NewString(surfaceId);
191 }
192 
JsSetXComponentSurfaceSize(const shared_ptr<JsRuntime> & runtime,const std::string & arguments,NodeId nodeId)193 void JsiXComponentBridge::JsSetXComponentSurfaceSize(
194     const shared_ptr<JsRuntime>& runtime, const std::string& arguments, NodeId nodeId)
195 {
196     if (!runtime) {
197         LOGE("JsSetXComponentSurfaceSize failed. runtime is null.");
198         return;
199     }
200     auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
201     if (!engine) {
202         LOGE("JsSetXComponentSurfaceSize failed. engine is null.");
203         return;
204     }
205     auto page = engine->GetRunningPage();
206     if (!page) {
207         LOGE("JsSetXComponentSurfaceSize failed. page is null.");
208         return;
209     }
210     auto task = [nodeId, page, arguments]() {
211         auto domDoc = page->GetDomDocument();
212         if (!domDoc) {
213             return;
214         }
215         auto domXComponent = AceType::DynamicCast<DOMXComponent>(domDoc->GetDOMNodeById(nodeId));
216         if (!domXComponent) {
217             return;
218         }
219 
220         std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(arguments);
221         if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() < 1) {
222             LOGE("JsSetXComponentSurfaceSize failed. parse args error");
223             return;
224         }
225         std::unique_ptr<JsonValue> surfaceSizePara = argsValue->GetArrayItem(0);
226         uint32_t surfaceWidth = surfaceSizePara->GetUInt("surfaceWidth", 0);
227         uint32_t surfaceHeight = surfaceSizePara->GetUInt("surfaceHeight", 0);
228         domXComponent->SetSurfaceSize(surfaceWidth, surfaceHeight);
229     };
230     auto delegate = engine->GetFrontendDelegate();
231     if (!delegate) {
232         LOGE("JsSetXComponentSurfaceSize failed. delegate is null.");
233         return;
234     }
235     delegate->PostSyncTaskToPage(task);
236 }
237 } // namespace OHOS::Ace::Framework