1 /*
2 * Copyright (c) 2025 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 #include "bridge/arkts_frontend/arkts_plugin_frontend.h"
16
17 #include <ani.h>
18
19 #include "interfaces/inner_api/ace/constants.h"
20 #include "bridge/arkts_frontend/arkts_ani_utils.h"
21 #include "bridge/arkts_frontend/entry/arkts_entry_loader.h"
22 #include "core/pipeline/pipeline_context.h"
23
24 namespace OHOS::Ace {
25 namespace {
26 /* copied from arkcompiler_ets_frontend vmloader.cc*/
27 struct AppInfo {
28 const char* className;
29 const char* createMethodName;
30 const char* createMethodSig;
31 const char* startMethodName;
32 const char* startMethodSig;
33 const char* enterMethodName;
34 const char* enterMethodSig;
35 const char* emitEventMethodName;
36 const char* emitEventMethodSig;
37 };
38 /* copied from arkcompiler_ets_frontend vmloader.cc*/
39 const AppInfo KOALA_APP_INFO = {
40 "Larkui/ArkUIEntry/Application;",
41 "createApplication",
42 "Lstd/core/String;Lstd/core/String;ZLstd/core/String;Larkui/UserView/UserView;Larkui/UserView/EntryPoint;"
43 ":Larkui/ArkUIEntry/Application;",
44 "start",
45 ":J",
46 "enter",
47 "IIJ:Z",
48 "emitEvent",
49 "IIII:V",
50 };
51
RunArkoalaEventLoop(ani_env * env,ani_ref app)52 void RunArkoalaEventLoop(ani_env* env, ani_ref app)
53 {
54 ani_class appClass;
55 ANI_CALL(env, FindClass(KOALA_APP_INFO.className, &appClass), return);
56
57 ani_method enter = nullptr;
58 ANI_CALL(env, Class_FindMethod(
59 appClass, KOALA_APP_INFO.enterMethodName, KOALA_APP_INFO.enterMethodSig, &enter), return);
60
61 ani_int arg0 = 0;
62 ani_int arg1 = 0;
63 ani_boolean result;
64 ANI_CALL(env, Object_CallMethod_Boolean(
65 static_cast<ani_object>(app), enter, &result, arg0, arg1, nullptr), return);
66 }
67 } // namespace
68
RunPage(const std::shared_ptr<std::vector<uint8_t>> & content,const std::string & params)69 UIContentErrorCode ArktsPluginFrontend::RunPage(
70 const std::shared_ptr<std::vector<uint8_t>>& content, const std::string& params)
71 {
72 return UIContentErrorCode::NO_ERRORS;
73 }
74
RunPage(const std::string & url,const std::string & params)75 UIContentErrorCode ArktsPluginFrontend::RunPage(const std::string& url, const std::string& params)
76 {
77 std::vector<uint8_t> abcContent;
78 if (!Framework::GetAssetContentImpl(assetManager_, "ets/modules_static.abc", abcContent)) {
79 LOGE("GetAssetContent fail: ets/modules_static.abc");
80 return UIContentErrorCode::INVALID_URL;
81 }
82
83 ani_class appClass{};
84 ANI_CALL(env_, FindClass(KOALA_APP_INFO.className, &appClass), return UIContentErrorCode::INVALID_URL);
85
86 ani_static_method create;
87 ANI_CALL(env_, Class_FindStaticMethod(appClass, KOALA_APP_INFO.createMethodName, KOALA_APP_INFO.createMethodSig,
88 &create), return UIContentErrorCode::INVALID_URL);
89
90 std::string appUrl = url.substr(0, url.rfind(".js"));
91
92 ani_string aniUrl{};
93 env_->String_NewUTF8(appUrl.c_str(), appUrl.size(), &aniUrl);
94
95 ani_string aniParams{};
96 env_->String_NewUTF8(params.c_str(), params.size(), &aniParams);
97
98 NG::EntryLoader entryLoader {env_, abcContent};
99 if (!entryLoader) {
100 return UIContentErrorCode::INVALID_URL;
101 }
102
103 std::string entryPath = pluginModuleName_ + "/src/main/ets/" + appUrl + "/__EntryWrapper";
104 ani_object entryPointObj = entryLoader.GetPageEntryObj(entryPath);
105
106 std::string legacyEntryPath = pluginModuleName_ + "/src/main/ets/" + appUrl + "/ComExampleTrivialApplication";
107 ani_object legacyEntryPointObj = entryPointObj ? nullptr : entryLoader.GetPageEntryObj(legacyEntryPath);
108
109 ani_string module{};
110 env_->String_NewUTF8(pluginModuleName_.c_str(), pluginModuleName_.size(), &module);
111
112 ani_ref appLocal{};
113 ANI_CALL(env_, Class_CallStaticMethod_Ref(appClass, create, &appLocal, aniUrl, aniParams, false, module,
114 legacyEntryPointObj, entryPointObj), return UIContentErrorCode::INVALID_URL);
115
116 env_->GlobalReference_Create(appLocal, &app_);
117
118 ani_method start;
119 ANI_CALL(env_, Class_FindMethod(appClass, KOALA_APP_INFO.startMethodName, KOALA_APP_INFO.startMethodSig, &start),
120 return UIContentErrorCode::INVALID_URL);
121
122 ani_long result;
123 ANI_CALL(env_, Object_CallMethod_Long(static_cast<ani_object>(app_), start, &result),
124 return UIContentErrorCode::INVALID_URL);
125
126 CHECK_NULL_RETURN(pipeline_, UIContentErrorCode::NULL_POINTER);
127 pipeline_->SetVsyncListener([env = env_, app = app_]() { RunArkoalaEventLoop(env, app); });
128
129 return UIContentErrorCode::NO_ERRORS;
130 }
131
AttachPipelineContext(const RefPtr<PipelineBase> & context)132 void ArktsPluginFrontend::AttachPipelineContext(const RefPtr<PipelineBase>& context)
133 {
134 pipeline_ = DynamicCast<PipelineContext>(context);
135 if (accessibilityManager_) {
136 accessibilityManager_->SetPipelineContext(context);
137 accessibilityManager_->InitializeCallback();
138 }
139 }
140
Destroy()141 void ArktsPluginFrontend::Destroy()
142 {
143 CHECK_NULL_VOID(env_);
144 env_->GlobalReference_Delete(app_);
145 }
146
147 } // namespace OHOS::Ace
148