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/v8/v8_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/v8/v8_engine.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 {
V8XComponentBridge()28 V8XComponentBridge::V8XComponentBridge()
29 {
30 nativeXComponentImpl_ = AceType::MakeRefPtr<NativeXComponentImpl>();
31 nativeXComponent_ = new OH_NativeXComponent(AceType::RawPtr(nativeXComponentImpl_));
32 }
33
~V8XComponentBridge()34 V8XComponentBridge::~V8XComponentBridge()
35 {
36 if (nativeXComponent_) {
37 delete nativeXComponent_;
38 nativeXComponent_ = nullptr;
39 }
40 }
41
HandleContext(const v8::Local<v8::Context> & ctx,NodeId id,const std::string & args,JsEngineInstance * engine)42 void V8XComponentBridge::HandleContext(const v8::Local<v8::Context>& ctx, NodeId id,
43 const std::string& args, JsEngineInstance* engine)
44 {
45 isolate_ = ctx->GetIsolate();
46 if (!isolate_) {
47 LOGE("V8XComponentBridge isolate_ is null.");
48 return;
49 }
50 ctx_.Reset(isolate_, ctx);
51
52 if (hasPluginLoaded_) {
53 return;
54 }
55
56 auto page = static_cast<RefPtr<JsAcePage>*>(ctx->GetIsolate()->GetData(V8EngineInstance::RUNNING_PAGE));
57 if (!page) {
58 LOGE("V8XComponentBridge page is null.");
59 return;
60 }
61 auto domXcomponent = AceType::DynamicCast<DOMXComponent>((*page)->GetDomDocument()->GetDOMNodeById(id));
62 if (!domXcomponent) {
63 LOGE("V8XComponentBridge domXcomponent is null.");
64 return;
65 }
66 auto xcomponent = AceType::DynamicCast<XComponentComponent>(domXcomponent->GetSpecializedComponent());
67 if (!xcomponent) {
68 LOGE("V8XComponentBridge xcomponent is null.");
69 return;
70 }
71 auto textureId = static_cast<int64_t>(xcomponent->GetTextureId());
72
73 auto container = Container::Current();
74 if (!container) {
75 LOGE("V8XComponentBridge Current container null");
76 return;
77 }
78 auto nativeView = static_cast<AceView*>(container->GetView());
79 if (!nativeView) {
80 LOGE("V8XComponentBridge nativeView null");
81 return;
82 }
83 auto nativeWindow = const_cast<void*>(nativeView->GetNativeWindowById(textureId));
84 if (!nativeWindow) {
85 LOGE("V8XComponentBridge::HandleJsContext nativeWindow invalid");
86 return;
87 }
88
89 nativeXComponentImpl_->SetSurface(nativeWindow);
90 nativeXComponentImpl_->SetXComponentId(xcomponent->GetId());
91
92 std::shared_ptr<V8NativeEngine> nativeEngine = static_cast<V8EngineInstance*>(engine)->GetV8NativeEngine();
93 if (!nativeEngine) {
94 LOGE("nativeEngine is null");
95 return;
96 }
97
98 auto renderContext = nativeEngine->LoadModuleByName(xcomponent->GetLibraryName(), true,
99 args, OH_NATIVE_XCOMPONENT_OBJ,
100 reinterpret_cast<void*>(nativeXComponent_));
101 renderContext_.Reset(isolate_, renderContext);
102 auto delegate = static_cast<RefPtr<FrontendDelegate>*>(isolate_->GetData(V8EngineInstance::FRONTEND_DELEGATE));
103 auto task = [weak = WeakClaim(this), xcomponent]() {
104 auto pool = xcomponent->GetTaskPool();
105 if (!pool) {
106 return;
107 }
108 auto bridge = weak.Upgrade();
109 if (bridge) {
110 pool->NativeXComponentInit(
111 bridge->nativeXComponent_,
112 AceType::WeakClaim(AceType::RawPtr(bridge->nativeXComponentImpl_)));
113 }
114 };
115 if (*delegate == nullptr) {
116 LOGE("delegate is null.");
117 return;
118 }
119 (*delegate)->PostSyncTaskToPage(task);
120 hasPluginLoaded_ = true;
121 return;
122 }
123
JsGetXComponentSurfaceId(v8::Isolate * isolate,NodeId nodeId)124 v8::Local<v8::String> V8XComponentBridge::JsGetXComponentSurfaceId(v8::Isolate* isolate, NodeId nodeId)
125 {
126 if (!isolate) {
127 return v8::Local<v8::String>();
128 }
129 auto page = static_cast<RefPtr<JsAcePage>*>(isolate->GetData(V8EngineInstance::RUNNING_PAGE));
130 if (page == nullptr) {
131 return v8::Local<v8::String>();
132 }
133
134 std::string surfaceId = "";
135 auto task = [nodeId, page, &surfaceId]() {
136 auto domDoc = (*page)->GetDomDocument();
137 if (!domDoc) {
138 return;
139 }
140 auto domXComponent = AceType::DynamicCast<DOMXComponent>(domDoc->GetDOMNodeById(nodeId));
141 if (!domXComponent) {
142 return;
143 }
144 surfaceId = domXComponent->GetSurfaceId();
145 };
146
147 auto delegate = static_cast<RefPtr<FrontendDelegate>*>(isolate->GetData(V8EngineInstance::FRONTEND_DELEGATE));
148 if (delegate == nullptr) {
149 return v8::Local<v8::String>();
150 }
151 (*delegate)->PostSyncTaskToPage(task);
152
153 return v8::String::NewFromUtf8(isolate, surfaceId.c_str()).ToLocalChecked();
154 }
155
JsSetXComponentSurfaceSize(const v8::FunctionCallbackInfo<v8::Value> & args,const std::string & arguments,NodeId nodeId)156 void V8XComponentBridge::JsSetXComponentSurfaceSize(
157 const v8::FunctionCallbackInfo<v8::Value>& args, const std::string& arguments, NodeId nodeId)
158 {
159 v8::Isolate* isolate = args.GetIsolate();
160 if (isolate == nullptr) {
161 LOGE("JsSetXComponentSurfaceSize isolate is null!");
162 return;
163 }
164 v8::HandleScope handleScope(isolate);
165 auto context = isolate->GetCurrentContext();
166 if (context.IsEmpty()) {
167 LOGE("JsSetXComponentSurfaceSize context is empty!");
168 return;
169 }
170 v8::Local<v8::External> data = v8::Local<v8::External>::Cast(args.Data());
171 V8EngineInstance* engineInstance = static_cast<V8EngineInstance*>(data->Value());
172 if (engineInstance == nullptr) {
173 LOGE("JsSetXComponentSurfaceSize engineInstance is null!");
174 return;
175 }
176
177 auto page = static_cast<RefPtr<JsAcePage>*>(isolate->GetData(V8EngineInstance::RUNNING_PAGE));
178 if (page == nullptr) {
179 LOGE("JsSetXComponentSurfaceSize page is null");
180 return;
181 }
182
183 auto task = [nodeId, page, arguments]() {
184 auto domDoc = (*page)->GetDomDocument();
185 if (!domDoc) {
186 LOGE("JsSetXComponentSurfaceSize dom document is null!");
187 return;
188 }
189
190 auto domXComponent = AceType::DynamicCast<DOMXComponent>(domDoc->GetDOMNodeById(nodeId));
191 if (!domXComponent) {
192 return;
193 }
194
195 std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(arguments);
196 if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() < 1) {
197 LOGE("JsSetXComponentSurfaceSize failed. parse args error");
198 return;
199 }
200 std::unique_ptr<JsonValue> surfaceSizePara = argsValue->GetArrayItem(0);
201 uint32_t surfaceWidth = surfaceSizePara->GetUInt("surfaceWidth", 0);
202 uint32_t surfaceHeight = surfaceSizePara->GetUInt("surfaceHeight", 0);
203 domXComponent->SetSurfaceSize(surfaceWidth, surfaceHeight);
204 };
205
206 auto delegate = engineInstance->GetDelegate();
207 if (!delegate) {
208 LOGE("JsSetXComponentSurfaceSize delegate is null");
209 return;
210 }
211 delegate->PostSyncTaskToPage(task);
212 }
213 } // namespace OHOS::Ace::Framework