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