1 /*
2 * Copyright (c) 2022-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
16 #include <regex>
17 #include "js_module_reader.h"
18
19 #include "bundle_info.h"
20 #include "bundle_mgr_helper.h"
21 #include "bundle_mgr_proxy.h"
22 #include "file_path_utils.h"
23 #include "hilog_tag_wrapper.h"
24 #include "hitrace_meter.h"
25 #include "iservice_registry.h"
26 #include "js_runtime_utils.h"
27 #include "singleton.h"
28 #include "system_ability_definition.h"
29
30 using namespace OHOS::AbilityBase;
31
32 namespace OHOS {
33 namespace AbilityRuntime {
34 using IBundleMgr = AppExecFwk::IBundleMgr;
35 bool JsModuleReader::needFindPluginHsp_ = true;
36
JsModuleReader(const std::string & bundleName,const std::string & hapPath,bool isFormRender)37 JsModuleReader::JsModuleReader(const std::string& bundleName, const std::string& hapPath, bool isFormRender)
38 : JsModuleSearcher(bundleName), isFormRender_(isFormRender)
39 {
40 if (!hapPath.empty() && hapPath.find(std::string(ABS_DATA_CODE_PATH)) != 0) {
41 isSystemPath_ = true;
42 } else {
43 isSystemPath_ = false;
44 }
45 }
46
operator ()(const std::string & inputPath,uint8_t ** buff,size_t * buffSize,std::string & errorMsg) const47 bool JsModuleReader::operator()(const std::string& inputPath, uint8_t **buff,
48 size_t *buffSize, std::string& errorMsg) const
49 {
50 TAG_LOGD(AAFwkTag::JSRUNTIME, "called start: %{private}s", inputPath.c_str());
51 std::string connector = "##";
52 std::string traceName = __PRETTY_FUNCTION__ + connector + inputPath;
53 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, traceName);
54 if (inputPath.empty() || buff == nullptr || buffSize == nullptr) {
55 TAG_LOGE(AAFwkTag::JSRUNTIME, "Invalid param");
56 return false;
57 }
58
59 auto realHapPath = GetAppHspPath(inputPath);
60 if (realHapPath.empty()) {
61 TAG_LOGE(AAFwkTag::JSRUNTIME, "empty realHapPath");
62 return false;
63 }
64
65 if (needFindPluginHsp_) {
66 // find plugin
67 realHapPath = GetPluginHspPath(inputPath);
68 if (realHapPath.empty()) {
69 TAG_LOGE(AAFwkTag::JSRUNTIME, "empty realHapPath");
70 return false;
71 }
72 needFindPluginHsp_ = true;
73 }
74
75 bool newCreate = false;
76 std::shared_ptr<Extractor> extractor = ExtractorUtil::GetExtractor(realHapPath, newCreate);
77 if (extractor == nullptr) {
78 errorMsg = "hap path error: " + realHapPath;
79 TAG_LOGE(AAFwkTag::JSRUNTIME, "realHapPath %{private}s GetExtractor failed", realHapPath.c_str());
80 return false;
81 }
82
83 auto data = extractor->GetSafeData(MERGE_ABC_PATH);
84 if (!data) {
85 TAG_LOGE(AAFwkTag::JSRUNTIME, "null data");
86 return false;
87 }
88
89 *buff = data->GetDataPtr();
90 *buffSize = data->GetDataLen();
91 return true;
92 }
93
GetPluginHspPath(const std::string & inputPath) const94 std::string JsModuleReader::GetPluginHspPath(const std::string& inputPath) const
95 {
96 std::string presetAppHapPath = "";
97 auto bundleMgrHelper = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
98 if (bundleMgrHelper == nullptr) {
99 TAG_LOGE(AAFwkTag::JSRUNTIME, "null bundleMgrHelper");
100 return presetAppHapPath;
101 }
102 std::string moduleName = inputPath.substr(inputPath.find_last_of("/") + 1);
103 std::string tmpPath = inputPath.substr(inputPath.find_first_of("/") + 1);
104 const std::string sharedBundleName = tmpPath.substr(0, tmpPath.find_first_of("/"));
105 TAG_LOGI(AAFwkTag::JSRUNTIME, "moduleName: %{public}s, sharedBundleName: %{public}s",
106 moduleName.c_str(), sharedBundleName.c_str());
107 if (moduleName.empty() || sharedBundleName.empty()) {
108 TAG_LOGE(AAFwkTag::JSRUNTIME, "empty moduleName");
109 return presetAppHapPath;
110 }
111
112 std::vector<AppExecFwk::PluginBundleInfo> pluginBundleInfos;
113 if (bundleMgrHelper->GetPluginInfosForSelf(pluginBundleInfos) != ERR_OK) {
114 TAG_LOGE(AAFwkTag::JSRUNTIME, "GetPluginInfosForSelf failed");
115 return presetAppHapPath;
116 }
117
118 for (auto &pluginBundleInfo : pluginBundleInfos) {
119 for (auto &pluginModuleInfo : pluginBundleInfo.pluginModuleInfos) {
120 if (moduleName == pluginModuleInfo.moduleName
121 && sharedBundleName == pluginBundleInfo.pluginBundleName) {
122 presetAppHapPath = pluginModuleInfo.hapPath;
123 TAG_LOGD(AAFwkTag::JSRUNTIME, "presetAppHapPath %{public}s", presetAppHapPath.c_str());
124 std::regex pattern(std::string(ABS_DATA_CODE_PATH) + bundleName_ + "/");
125 presetAppHapPath = std::regex_replace(
126 presetAppHapPath, pattern, std::string(ABS_CODE_PATH) + std::string(BUNDLE));
127 TAG_LOGD(AAFwkTag::JSRUNTIME, "presetAppHapPath %{public}s", presetAppHapPath.c_str());
128 return presetAppHapPath;
129 }
130 }
131 }
132 TAG_LOGE(AAFwkTag::JSRUNTIME, "GetPluginHspPath failed");
133 return presetAppHapPath;
134 }
135
GetAppHspPath(const std::string & inputPath) const136 std::string JsModuleReader::GetAppHspPath(const std::string& inputPath) const
137 {
138 if (isFormRender_) {
139 return GetFormAppHspPath(inputPath);
140 }
141 return GetCommonAppHspPath(inputPath);
142 }
143
GetFormAppHspPath(const std::string & inputPath) const144 std::string JsModuleReader::GetFormAppHspPath(const std::string& inputPath) const
145 {
146 std::string realHapPath;
147 std::string suffix = std::string(SHARED_FILE_SUFFIX);
148 realHapPath.append("/data/bundles/")
149 .append(bundleName_).append("/")
150 .append(GetModuleName(inputPath))
151 .append(SHARED_FILE_SUFFIX);
152
153 TAG_LOGI(AAFwkTag::JSRUNTIME, "realHapPath: %{private}s", realHapPath.c_str());
154 if (realHapPath.empty() ||
155 realHapPath.length() < suffix.length() ||
156 realHapPath.compare(realHapPath.length() - suffix.length(), suffix.length(), suffix) != 0) {
157 TAG_LOGE(AAFwkTag::JSRUNTIME, "obtain realHapPath failed");
158 return realHapPath;
159 }
160 return realHapPath;
161 }
162
GetModuleName(const std::string & inputPath) const163 std::string JsModuleReader::GetModuleName(const std::string& inputPath) const
164 {
165 return inputPath.substr(inputPath.find_last_of("/") + 1);
166 }
167
GetCommonAppHspPath(const std::string & inputPath) const168 std::string JsModuleReader::GetCommonAppHspPath(const std::string& inputPath) const
169 {
170 std::string suffix = std::string(SHARED_FILE_SUFFIX);
171 std::string realHapPath = GetPresetAppHapPath(inputPath, bundleName_);
172 if ((realHapPath.find(ABS_DATA_CODE_PATH) == 0) || (realHapPath == inputPath)) {
173 realHapPath = std::string(ABS_CODE_PATH) + inputPath + suffix;
174 }
175
176 TAG_LOGD(AAFwkTag::JSRUNTIME, "realHapPath: %{private}s", realHapPath.c_str());
177 if (realHapPath.empty() ||
178 realHapPath.length() < suffix.length() ||
179 realHapPath.compare(realHapPath.length() - suffix.length(), suffix.length(), suffix) != 0) {
180 TAG_LOGE(AAFwkTag::JSRUNTIME, "obtain realHapPath failed");
181 return realHapPath;
182 }
183 return realHapPath;
184 }
185
GetOtherHspPath(const std::string & bundleName,const std::string & moduleName,const std::string & inputPath)186 std::string JsModuleReader::GetOtherHspPath(const std::string& bundleName, const std::string& moduleName,
187 const std::string& inputPath)
188 {
189 std::string presetAppHapPath = inputPath;
190
191 auto bundleMgrHelper = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
192 if (bundleMgrHelper == nullptr) {
193 TAG_LOGE(AAFwkTag::JSRUNTIME, "null bundleMgrHelper");
194 return presetAppHapPath;
195 }
196
197 std::vector<AppExecFwk::BaseSharedBundleInfo> baseSharedBundleInfos;
198 if (bundleMgrHelper->GetBaseSharedBundleInfos(bundleName, baseSharedBundleInfos) != 0) {
199 TAG_LOGE(AAFwkTag::JSRUNTIME, "GetBaseSharedBundleInfos failed");
200 return presetAppHapPath;
201 }
202 std::string tmpPath = inputPath.substr(inputPath.find_first_of("/") + 1);
203 const std::string sharedBundleName = tmpPath.substr(0, tmpPath.find_first_of("/"));
204 for (const auto &info : baseSharedBundleInfos) {
205 if ((info.bundleName == sharedBundleName) && (info.moduleName == moduleName)) {
206 presetAppHapPath = info.hapPath;
207 needFindPluginHsp_ = false;
208 break;
209 }
210 }
211 AppExecFwk::BundleInfo bundleInfo;
212 int32_t ret = bundleMgrHelper->GetDependentBundleInfo(sharedBundleName, bundleInfo,
213 AppExecFwk::GetDependentBundleInfoFlag::GET_APP_SERVICE_HSP_BUNDLE_INFO);
214 if (ret != ERR_OK) {
215 TAG_LOGE(AAFwkTag::JSRUNTIME, "GetDependentBundleInfo failed");
216 return presetAppHapPath;
217 }
218 for (const auto &info : bundleInfo.hapModuleInfos) {
219 if (info.moduleName == moduleName) {
220 presetAppHapPath = info.hapPath;
221 needFindPluginHsp_ = false;
222 break;
223 }
224 }
225 return presetAppHapPath;
226 }
227
GetPresetAppHapPath(const std::string & inputPath,const std::string & bundleName)228 std::string JsModuleReader::GetPresetAppHapPath(const std::string& inputPath, const std::string& bundleName)
229 {
230 std::string presetAppHapPath = inputPath;
231 std::string moduleName = inputPath.substr(inputPath.find_last_of("/") + 1);
232 if (moduleName.empty()) {
233 TAG_LOGE(AAFwkTag::JSRUNTIME, "empty moduleName");
234 return presetAppHapPath;
235 }
236 auto bundleMgrHelper = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
237 if (bundleMgrHelper == nullptr) {
238 TAG_LOGE(AAFwkTag::JSRUNTIME, "null bundleMgrHelper");
239 return presetAppHapPath;
240 }
241 if (inputPath.find_first_of("/") == inputPath.find_last_of("/")) {
242 AppExecFwk::BundleInfo bundleInfo;
243 auto getInfoResult = bundleMgrHelper->GetBundleInfoForSelf(static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::
244 GET_BUNDLE_INFO_WITH_HAP_MODULE), bundleInfo);
245 if (getInfoResult != 0 || bundleInfo.hapModuleInfos.empty()) {
246 TAG_LOGE(AAFwkTag::JSRUNTIME, "GetBundleInfoForSelf failed");
247 return presetAppHapPath;
248 }
249 for (auto hapModuleInfo : bundleInfo.hapModuleInfos) {
250 if (hapModuleInfo.moduleName == moduleName) {
251 presetAppHapPath = hapModuleInfo.hapPath;
252 needFindPluginHsp_ = false;
253 break;
254 }
255 }
256 } else {
257 presetAppHapPath = GetOtherHspPath(bundleName, moduleName, presetAppHapPath);
258 }
259 return presetAppHapPath;
260 }
261
GetHapPathList(const std::string & bundleName,std::vector<std::string> & hapList)262 void JsModuleReader::GetHapPathList(const std::string &bundleName, std::vector<std::string> &hapList)
263 {
264 auto bundleMgrHelper = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
265 if (bundleMgrHelper == nullptr) {
266 TAG_LOGE(AAFwkTag::JSRUNTIME, "null bundleMgrHelper");
267 return;
268 }
269 AppExecFwk::BundleInfo bundleInfo;
270 auto getInfoResult = bundleMgrHelper->GetBundleInfoForSelf(static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::
271 GET_BUNDLE_INFO_WITH_HAP_MODULE), bundleInfo);
272 if (getInfoResult != 0 || bundleInfo.hapModuleInfos.empty()) {
273 TAG_LOGE(AAFwkTag::JSRUNTIME, "GetBundleInfoForSelf failed");
274 return;
275 }
276 for (auto hapModuleInfo : bundleInfo.hapModuleInfos) {
277 hapList.emplace_back(hapModuleInfo.hapPath);
278 }
279 }
280 } // namespace AbilityRuntime
281 } // namespace OHOS