1 /*
2  * Copyright (c) 2022-2024 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 "js_module_reader.h"
17 
18 #include "bundle_info.h"
19 #include "bundle_mgr_helper.h"
20 #include "bundle_mgr_proxy.h"
21 #include "file_path_utils.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 #include "system_ability_definition.h"
28 
29 using namespace OHOS::AbilityBase;
30 
31 namespace OHOS {
32 namespace AbilityRuntime {
33 using IBundleMgr = AppExecFwk::IBundleMgr;
34 
JsModuleReader(const std::string & bundleName,const std::string & hapPath,bool isFormRender)35 JsModuleReader::JsModuleReader(const std::string& bundleName, const std::string& hapPath, bool isFormRender)
36     : JsModuleSearcher(bundleName), isFormRender_(isFormRender)
37 {
38     if (!hapPath.empty() && hapPath.find(std::string(ABS_DATA_CODE_PATH)) != 0) {
39         isSystemPath_ = true;
40     } else {
41         isSystemPath_ = false;
42     }
43 }
44 
operator ()(const std::string & inputPath,uint8_t ** buff,size_t * buffSize,std::string & errorMsg) const45 bool JsModuleReader::operator()(const std::string& inputPath, uint8_t **buff,
46     size_t *buffSize, std::string& errorMsg) const
47 {
48     TAG_LOGD(AAFwkTag::JSRUNTIME, "called start: %{private}s", inputPath.c_str());
49     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
50     if (inputPath.empty() || buff == nullptr || buffSize == nullptr) {
51         TAG_LOGE(AAFwkTag::JSRUNTIME, "Invalid param");
52         return false;
53     }
54 
55     auto realHapPath = GetAppHspPath(inputPath);
56     if (realHapPath.empty()) {
57         TAG_LOGE(AAFwkTag::JSRUNTIME, "empty realHapPath");
58         return false;
59     }
60 
61     bool newCreate = false;
62     std::shared_ptr<Extractor> extractor = ExtractorUtil::GetExtractor(realHapPath, newCreate);
63     if (extractor == nullptr) {
64         errorMsg = "hap path error: " + realHapPath;
65         TAG_LOGE(AAFwkTag::JSRUNTIME, "realHapPath %{private}s GetExtractor failed", realHapPath.c_str());
66         return false;
67     }
68 
69     auto data = extractor->GetSafeData(MERGE_ABC_PATH);
70     if (!data) {
71         TAG_LOGE(AAFwkTag::JSRUNTIME, "null data");
72         return false;
73     }
74 
75     *buff = data->GetDataPtr();
76     *buffSize = data->GetDataLen();
77     return true;
78 }
79 
GetAppHspPath(const std::string & inputPath) const80 std::string JsModuleReader::GetAppHspPath(const std::string& inputPath) const
81 {
82     if (isFormRender_) {
83         return GetFormAppHspPath(inputPath);
84     }
85     return GetCommonAppHspPath(inputPath);
86 }
87 
GetFormAppHspPath(const std::string & inputPath) const88 std::string JsModuleReader::GetFormAppHspPath(const std::string& inputPath) const
89 {
90     std::string realHapPath;
91     std::string suffix = std::string(SHARED_FILE_SUFFIX);
92     realHapPath.append("/data/bundles/")
93         .append(bundleName_).append("/")
94         .append(GetModuleName(inputPath))
95         .append(SHARED_FILE_SUFFIX);
96 
97     TAG_LOGI(AAFwkTag::JSRUNTIME, "realHapPath: %{private}s", realHapPath.c_str());
98     if (realHapPath.empty() ||
99         realHapPath.length() < suffix.length() ||
100         realHapPath.compare(realHapPath.length() - suffix.length(), suffix.length(), suffix) != 0) {
101         TAG_LOGE(AAFwkTag::JSRUNTIME, "failed to obtain realHapPath");
102         return realHapPath;
103     }
104     return realHapPath;
105 }
106 
GetModuleName(const std::string & inputPath) const107 std::string JsModuleReader::GetModuleName(const std::string& inputPath) const
108 {
109     return inputPath.substr(inputPath.find_last_of("/") + 1);
110 }
111 
GetCommonAppHspPath(const std::string & inputPath) const112 std::string JsModuleReader::GetCommonAppHspPath(const std::string& inputPath) const
113 {
114     std::string suffix = std::string(SHARED_FILE_SUFFIX);
115     std::string realHapPath = GetPresetAppHapPath(inputPath, bundleName_);
116     if ((realHapPath.find(ABS_DATA_CODE_PATH) == 0) || (realHapPath == inputPath)) {
117         realHapPath = std::string(ABS_CODE_PATH) + inputPath + suffix;
118     }
119 
120     TAG_LOGD(AAFwkTag::JSRUNTIME, "realHapPath: %{private}s", realHapPath.c_str());
121     if (realHapPath.empty() ||
122         realHapPath.length() < suffix.length() ||
123         realHapPath.compare(realHapPath.length() - suffix.length(), suffix.length(), suffix) != 0) {
124         TAG_LOGE(AAFwkTag::JSRUNTIME, "failed to obtain realHapPath");
125         return realHapPath;
126     }
127     return realHapPath;
128 }
129 
GetOtherHspPath(const std::string & bundleName,const std::string & moduleName,const std::string & inputPath)130 std::string JsModuleReader::GetOtherHspPath(const std::string& bundleName, const std::string& moduleName,
131     const std::string& inputPath)
132 {
133     std::string presetAppHapPath = inputPath;
134 
135     auto bundleMgrHelper = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
136     if (bundleMgrHelper == nullptr) {
137         TAG_LOGE(AAFwkTag::JSRUNTIME, "null bundleMgrHelper");
138         return presetAppHapPath;
139     }
140 
141     std::vector<AppExecFwk::BaseSharedBundleInfo> baseSharedBundleInfos;
142     if (bundleMgrHelper->GetBaseSharedBundleInfos(bundleName, baseSharedBundleInfos) != 0) {
143         TAG_LOGE(AAFwkTag::JSRUNTIME, "GetBaseSharedBundleInfos failed");
144         return presetAppHapPath;
145     }
146     std::string tmpPath = inputPath.substr(inputPath.find_first_of("/") + 1);
147     const std::string sharedBundleName = tmpPath.substr(0, tmpPath.find_first_of("/"));
148     for (const auto &info : baseSharedBundleInfos) {
149         if ((info.bundleName == sharedBundleName) && (info.moduleName == moduleName)) {
150             presetAppHapPath = info.hapPath;
151             break;
152         }
153     }
154     AppExecFwk::BundleInfo bundleInfo;
155     int32_t ret = bundleMgrHelper->GetDependentBundleInfo(sharedBundleName, bundleInfo,
156         AppExecFwk::GetDependentBundleInfoFlag::GET_APP_SERVICE_HSP_BUNDLE_INFO);
157     if (ret != ERR_OK) {
158         TAG_LOGE(AAFwkTag::JSRUNTIME, "GetDependentBundleInfo failed");
159         return presetAppHapPath;
160     }
161     for (const auto &info : bundleInfo.hapModuleInfos) {
162         if (info.moduleName == moduleName) {
163             presetAppHapPath = info.hapPath;
164             break;
165         }
166     }
167     return presetAppHapPath;
168 }
169 
GetPresetAppHapPath(const std::string & inputPath,const std::string & bundleName)170 std::string JsModuleReader::GetPresetAppHapPath(const std::string& inputPath, const std::string& bundleName)
171 {
172     std::string presetAppHapPath = inputPath;
173     std::string moduleName = inputPath.substr(inputPath.find_last_of("/") + 1);
174     if (moduleName.empty()) {
175         TAG_LOGE(AAFwkTag::JSRUNTIME, "empty moduleName");
176         return presetAppHapPath;
177     }
178     auto bundleMgrHelper = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
179     if (bundleMgrHelper == nullptr) {
180         TAG_LOGE(AAFwkTag::JSRUNTIME, "null bundleMgrHelper");
181         return presetAppHapPath;
182     }
183     if (inputPath.find_first_of("/") == inputPath.find_last_of("/")) {
184         AppExecFwk::BundleInfo bundleInfo;
185         auto getInfoResult = bundleMgrHelper->GetBundleInfoForSelf(static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::
186             GET_BUNDLE_INFO_WITH_HAP_MODULE), bundleInfo);
187         if (getInfoResult != 0 || bundleInfo.hapModuleInfos.empty()) {
188             TAG_LOGE(AAFwkTag::JSRUNTIME, "GetBundleInfoForSelf failed");
189             return presetAppHapPath;
190         }
191         for (auto hapModuleInfo : bundleInfo.hapModuleInfos) {
192             if (hapModuleInfo.moduleName == moduleName) {
193                 presetAppHapPath = hapModuleInfo.hapPath;
194                 break;
195             }
196         }
197     } else {
198         presetAppHapPath = GetOtherHspPath(bundleName, moduleName, presetAppHapPath);
199     }
200     return presetAppHapPath;
201 }
202 
GetHapPathList(const std::string & bundleName,std::vector<std::string> & hapList)203 void JsModuleReader::GetHapPathList(const std::string &bundleName, std::vector<std::string> &hapList)
204 {
205     auto systemAbilityManagerClient = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
206     if (!systemAbilityManagerClient) {
207         TAG_LOGE(AAFwkTag::JSRUNTIME, "null systemAbilityManagerClient");
208         return;
209     }
210     auto remoteObject = systemAbilityManagerClient->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
211     if (!remoteObject) {
212         TAG_LOGE(AAFwkTag::JSRUNTIME, "null remoteObject");
213         return;
214     }
215     auto bundleMgrProxy = iface_cast<IBundleMgr>(remoteObject);
216     AppExecFwk::BundleInfo bundleInfo;
217     auto getInfoResult = bundleMgrProxy->GetBundleInfoForSelf(static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::
218         GET_BUNDLE_INFO_WITH_HAP_MODULE), bundleInfo);
219     if (getInfoResult != 0 || bundleInfo.hapModuleInfos.empty()) {
220         TAG_LOGE(AAFwkTag::JSRUNTIME, "GetBundleInfoForSelf failed");
221         return;
222     }
223     for (auto hapModuleInfo : bundleInfo.hapModuleInfos) {
224         hapList.emplace_back(hapModuleInfo.hapPath);
225     }
226 }
227 } // namespace AbilityRuntime
228 } // namespace OHOS