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