• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "bridge/declarative_frontend/jsview/js_ui_extension.h"
17 
18 #include <functional>
19 #include <string>
20 
21 #include "base/log/ace_scoring_log.h"
22 #include "base/want/want_wrap.h"
23 #include "bridge/common/utils/engine_helper.h"
24 #include "bridge/declarative_frontend/engine/js_converter.h"
25 #include "bridge/declarative_frontend/jsview/js_utils.h"
26 #include "core/common/container_scope.h"
27 #include "core/components_ng/pattern/ui_extension/ui_extension_model.h"
28 #include "core/components_ng/pattern/ui_extension/ui_extension_model_ng.h"
29 
30 namespace OHOS::Ace {
31 std::unique_ptr<UIExtensionModel> UIExtensionModel::instance_ = nullptr;
32 std::mutex UIExtensionModel::mutex_;
33 
GetInstance()34 UIExtensionModel* UIExtensionModel::GetInstance()
35 {
36     if (!instance_) {
37         std::lock_guard<std::mutex> lock(mutex_);
38         if (!instance_) {
39 #ifdef NG_BUILD
40             instance_.reset(new NG::UIExtensionModelNG());
41 #else
42             if (Container::IsCurrentUseNewPipeline()) {
43                 instance_.reset(new NG::UIExtensionModelNG());
44             } else {
45                 return nullptr;
46             }
47 #endif
48         }
49     }
50     return instance_.get();
51 }
52 } // namespace OHOS::Ace
53 
54 namespace OHOS::Ace::Framework {
JSBind(BindingTarget globalObj)55 void JSUIExtensionProxy::JSBind(BindingTarget globalObj)
56 {
57     JSClass<JSUIExtensionProxy>::Declare("UIExtensionProxy ");
58     JSClass<JSUIExtensionProxy>::CustomMethod("send", &JSUIExtensionProxy::Send);
59     JSClass<JSUIExtensionProxy>::Bind(globalObj, &JSUIExtensionProxy::Constructor, &JSUIExtensionProxy::Destructor);
60 }
61 
Constructor(const JSCallbackInfo & info)62 void JSUIExtensionProxy::Constructor(const JSCallbackInfo& info)
63 {
64     auto uiExtensionProxy = Referenced::MakeRefPtr<JSUIExtensionProxy>();
65     uiExtensionProxy->IncRefCount();
66     info.SetReturnValue(Referenced::RawPtr(uiExtensionProxy));
67 }
68 
Destructor(JSUIExtensionProxy * uiExtensionProxy)69 void JSUIExtensionProxy::Destructor(JSUIExtensionProxy* uiExtensionProxy)
70 {
71     if (uiExtensionProxy != nullptr) {
72         uiExtensionProxy->DecRefCount();
73     }
74 }
75 
Send(const JSCallbackInfo & info)76 void JSUIExtensionProxy::Send(const JSCallbackInfo& info)
77 {
78     if (!info[0]->IsObject()) {
79         return;
80     }
81     ContainerScope scope(instanceId_);
82     auto engine = EngineHelper::GetCurrentEngine();
83     CHECK_NULL_VOID(engine);
84     NativeEngine* nativeEngine = engine->GetNativeEngine();
85     panda::Local<JsiValue> value = info[0].Get().GetLocalHandle();
86     JSValueWrapper valueWrapper = value;
87     ScopeRAII scopeRAII(nativeEngine->GetScopeManager());
88     NativeValue* nativeValue = nativeEngine->ValueToNativeValue(valueWrapper);
89     auto wantParams = WantParamsWrap::CreateWantWrap(nativeEngine, nativeValue);
90     if (proxy_) {
91         proxy_->SendData(wantParams);
92     }
93 }
94 
SetInstanceId(int32_t instanceId)95 void JSUIExtensionProxy::SetInstanceId(int32_t instanceId)
96 {
97     instanceId_ = instanceId;
98 }
99 
SetProxy(const RefPtr<NG::UIExtensionProxy> & proxy)100 void JSUIExtensionProxy::SetProxy(const RefPtr<NG::UIExtensionProxy>& proxy)
101 {
102     proxy_ = proxy;
103 }
104 
JSBind(BindingTarget globalObj)105 void JSUIExtension::JSBind(BindingTarget globalObj)
106 {
107     JSClass<JSUIExtension>::Declare("UIExtensionComponent");
108     MethodOptions opt = MethodOptions::NONE;
109     JSClass<JSUIExtension>::StaticMethod("create", &JSUIExtension::Create, opt);
110     JSClass<JSUIExtension>::StaticMethod("onRemoteReady", &JSUIExtension::OnRemoteReady);
111     JSClass<JSUIExtension>::StaticMethod("onReceive", &JSUIExtension::OnReceive);
112     JSClass<JSUIExtension>::StaticMethod("onRelease", &JSUIExtension::OnRelease);
113     JSClass<JSUIExtension>::StaticMethod("onResult", &JSUIExtension::OnResult);
114     JSClass<JSUIExtension>::StaticMethod("onError", &JSUIExtension::OnError);
115     JSClass<JSUIExtension>::InheritAndBind<JSViewAbstract>(globalObj);
116 }
117 
Create(const JSCallbackInfo & info)118 void JSUIExtension::Create(const JSCallbackInfo& info)
119 {
120     if (!info[0]->IsObject()) {
121         return;
122     }
123     auto wantObj = JSRef<JSObject>::Cast(info[0]);
124     RefPtr<OHOS::Ace::WantWrap> want = CreateWantWrapFromNapiValue(wantObj);
125     UIExtensionModel::GetInstance()->Create(want);
126 }
127 
OnRemoteReady(const JSCallbackInfo & info)128 void JSUIExtension::OnRemoteReady(const JSCallbackInfo& info)
129 {
130     if (!info[0]->IsFunction()) {
131         return;
132     }
133     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
134     auto instanceId = ContainerScope::CurrentId();
135     auto onRemoteReady = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId]
136         (const RefPtr<NG::UIExtensionProxy>& session) {
137         ContainerScope scope(instanceId);
138         JSRef<JSObject> contextObj = JSClass<JSUIExtensionProxy>::NewInstance();
139         RefPtr<JSUIExtensionProxy> proxy = Referenced::Claim(contextObj->Unwrap<JSUIExtensionProxy>());
140         proxy->SetInstanceId(instanceId);
141         proxy->SetProxy(session);
142         auto returnValue = JSRef<JSVal>::Cast(contextObj);
143         func->ExecuteJS(1, &returnValue);
144     };
145     UIExtensionModel::GetInstance()->SetOnRemoteReady(std::move(onRemoteReady));
146 }
147 
OnReceive(const JSCallbackInfo & info)148 void JSUIExtension::OnReceive(const JSCallbackInfo& info)
149 {
150     if (!info[0]->IsFunction()) {
151         return;
152     }
153     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
154     auto instanceId = ContainerScope::CurrentId();
155     auto onReceive = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId]
156         (const AAFwk::WantParams& wantParams) {
157         ContainerScope scope(instanceId);
158         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
159         ACE_SCORING_EVENT("UIExtensionComponent.UIExtensionDataSession.onReceive");
160         auto engine = EngineHelper::GetCurrentEngine();
161         CHECK_NULL_VOID(engine);
162         NativeEngine* nativeEngine = engine->GetNativeEngine();
163         CHECK_NULL_VOID(nativeEngine);
164         auto nativeWantParams = WantWrap::ConvertParamsToNativeValue(wantParams, nativeEngine);
165         auto wantParamsJSVal = JsConverter::ConvertNativeValueToJsVal(nativeWantParams);
166         func->ExecuteJS(1, &wantParamsJSVal);
167     };
168     UIExtensionModel::GetInstance()->SetOnReceive(std::move(onReceive));
169 }
170 
OnRelease(const JSCallbackInfo & info)171 void JSUIExtension::OnRelease(const JSCallbackInfo& info)
172 {
173     if (!info[0]->IsFunction()) {
174         return;
175     }
176     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
177     auto instanceId = ContainerScope::CurrentId();
178     auto onRelease = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId](int32_t releaseCode) {
179         ContainerScope scope(instanceId);
180         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
181         ACE_SCORING_EVENT("UIExtensionComponent.onRelease");
182         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(releaseCode));
183         func->ExecuteJS(1, &newJSVal);
184     };
185     UIExtensionModel::GetInstance()->SetOnRelease(std::move(onRelease));
186 }
187 
OnResult(const JSCallbackInfo & info)188 void JSUIExtension::OnResult(const JSCallbackInfo& info)
189 {
190     if (!info[0]->IsFunction()) {
191         return;
192     }
193     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
194     auto instanceId = ContainerScope::CurrentId();
195     auto onResult = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId]
196         (int32_t code, const AAFwk::Want& want) {
197             ContainerScope scope(instanceId);
198             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
199             ACE_SCORING_EVENT("UIExtensionComponent.onResult");
200             auto engine = EngineHelper::GetCurrentEngine();
201             CHECK_NULL_VOID(engine);
202             NativeEngine* nativeEngine = engine->GetNativeEngine();
203             CHECK_NULL_VOID(nativeEngine);
204             auto nativeWant = WantWrap::ConvertToNativeValue(want, nativeEngine);
205             auto wantJSVal = JsConverter::ConvertNativeValueToJsVal(nativeWant);
206             JSRef<JSObject> obj = JSRef<JSObject>::New();
207             obj->SetProperty<int32_t>("code", code);
208             obj->SetPropertyObject("want", wantJSVal);
209             auto returnValue = JSRef<JSVal>::Cast(obj);
210             func->ExecuteJS(1, &returnValue);
211         };
212     UIExtensionModel::GetInstance()->SetOnResult(std::move(onResult));
213 }
214 
OnError(const JSCallbackInfo & info)215 void JSUIExtension::OnError(const JSCallbackInfo& info)
216 {
217     if (!info[0]->IsFunction()) {
218         return;
219     }
220     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
221     auto instanceId = ContainerScope::CurrentId();
222     auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId]
223         (int32_t code, const std::string& name, const std::string& message) {
224             ContainerScope scope(instanceId);
225             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
226             ACE_SCORING_EVENT("UIExtensionComponent.onError");
227             JSRef<JSObject> obj = JSRef<JSObject>::New();
228             obj->SetProperty<int32_t>("code", code);
229             obj->SetProperty<std::string>("name", name);
230             obj->SetProperty<std::string>("message", message);
231             auto returnValue = JSRef<JSVal>::Cast(obj);
232             func->ExecuteJS(1, &returnValue);
233         };
234     UIExtensionModel::GetInstance()->SetOnError(std::move(onError));
235 }
236 } // namespace OHOS::Ace::Framework
237