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 "form_module_preloader.h"
17
18 #include "adapter/ohos/entrance/utils.h"
19 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h"
20
21
22 namespace OHOS::Ace {
23 namespace {
24 // KEY: bundleName, VALUE: formModuleList
25 std::unordered_map<std::string, std::unordered_set<std::string>> gFormModuleMap_;
26
27 std::mutex gMapLock_;
28 }
29 #ifdef FORM_SUPPORTED
OHOS_ACE_PreloadAceModuleCard(void* runtime, const char* bundleName, const void* hapPathMap)30 extern "C" ACE_FORCE_EXPORT void OHOS_ACE_PreloadAceModuleCard(void* runtime, const char* bundleName,
31 const void* hapPathMap)
32 {
33 std::unordered_set<std::string> formModuleList;
34 auto hapPathMapPtr = reinterpret_cast<const std::map<std::string, std::string>*>(hapPathMap);
35 if (!FormModulePreloader::CreateFormModuleList(std::string(bundleName), formModuleList, hapPathMapPtr)) {
36 TAG_LOGW(AceLogTag::ACE_FORM, "CreateFormModuleList failed, will load all modules later.");
37 }
38 Framework::JsiDeclarativeEngineInstance::PreloadAceModuleCard(runtime, formModuleList);
39 }
40
OHOS_ACE_ReloadAceModuleCard(void* runtime, const char* bundleName, const void* hapPathMap)41 extern "C" ACE_FORCE_EXPORT void OHOS_ACE_ReloadAceModuleCard(void* runtime, const char* bundleName,
42 const void* hapPathMap)
43 {
44 std::unordered_set<std::string> formModuleList;
45 auto hapPathMapPtr = reinterpret_cast<const std::map<std::string, std::string>*>(hapPathMap);
46 bool ret = FormModulePreloader::GetNewFormModuleList(std::string(bundleName), formModuleList, hapPathMapPtr);
47 if (ret && formModuleList.empty()) {
48 TAG_LOGI(AceLogTag::ACE_FORM, "There are no new components to load.");
49 return;
50 } else if (!ret) {
51 TAG_LOGW(AceLogTag::ACE_FORM, "GetNewFormModuleList failed, will load all modules later.");
52 formModuleList.clear(); // JsiDeclarativeEngineInstance will load all module if input list is empty.
53 }
54 Framework::JsiDeclarativeEngineInstance::ReloadAceModuleCard(runtime, formModuleList);
55 }
56 #endif
57
CreateFormModuleList(const std::string& bundleName, std::unordered_set<std::string>& formModuleList, const std::map<std::string, std::string>* hapPathMap)58 bool FormModulePreloader::CreateFormModuleList(const std::string& bundleName,
59 std::unordered_set<std::string>& formModuleList, const std::map<std::string, std::string>* hapPathMap)
60 {
61 if (ReadFormModuleList(bundleName, formModuleList, hapPathMap, false)) {
62 std::lock_guard<std::mutex> lock(gMapLock_);
63 gFormModuleMap_.emplace(bundleName, formModuleList);
64 TAG_LOGI(AceLogTag::ACE_FORM, "push formModuleList to map, bundleName: %{public}s.", bundleName.c_str());
65 return true;
66 }
67 return false;
68 }
69
GetNewFormModuleList(const std::string& bundleName, std::unordered_set<std::string>& formModuleList, const std::map<std::string, std::string>* hapPathMap)70 bool FormModulePreloader::GetNewFormModuleList(const std::string& bundleName,
71 std::unordered_set<std::string>& formModuleList, const std::map<std::string, std::string>* hapPathMap)
72 {
73 {
74 std::lock_guard<std::mutex> lock(gMapLock_);
75 if (gFormModuleMap_.find(bundleName) == gFormModuleMap_.end()) {
76 // This means that reading the list of components fails on preload
77 TAG_LOGW(AceLogTag::ACE_FORM, "All modules of bundle %{public}s have been loaded.", bundleName.c_str());
78 return true;
79 }
80 }
81 return ReadFormModuleList(bundleName, formModuleList, hapPathMap, true);
82 }
83
ReadFormModuleList(const std::string& bundleName, std::unordered_set<std::string>& formModuleList, const std::map<std::string, std::string>* hapPathMap, bool isReloadCondition)84 bool FormModulePreloader::ReadFormModuleList(const std::string& bundleName, std::unordered_set<std::string>&
85 formModuleList, const std::map<std::string, std::string>* hapPathMap, bool isReloadCondition)
86 {
87 if (hapPathMap == nullptr) {
88 TAG_LOGE(AceLogTag::ACE_FORM, "hapPathMap of bundle %{public}s is null.", bundleName.c_str());
89 return false;
90 }
91 TAG_LOGI(AceLogTag::ACE_FORM, "hapPaths size of bundle %{public}s is %{public}zu",
92 bundleName.c_str(), hapPathMap->size());
93 bool readSuccess = false;
94 for (auto hapPathPair: *hapPathMap) {
95 const std::string& hapPath = hapPathPair.second;
96 // Create HapAssetProvider
97 RefPtr<AssetManager> assetManager = CreateAssetManager(hapPath);
98 if (assetManager == nullptr) {
99 TAG_LOGW(AceLogTag::ACE_FORM, "CreateAssetManager failed, hapPath: %{private}s.", hapPath.c_str());
100 continue;
101 }
102 // Read component_collection.json
103 std::string content;
104 if (!ReadFileFromAssetManager(assetManager, "component_collection.json", content)) {
105 TAG_LOGW(
106 AceLogTag::ACE_FORM, "Read component_collection.json failed, hapPath: %{private}s.", hapPath.c_str());
107 continue;
108 }
109 // Parse component_collection.json
110 if (!ParseComponentCollectionJson(bundleName, content, formModuleList, isReloadCondition)) {
111 TAG_LOGW(
112 AceLogTag::ACE_FORM, "Parse component_collection.json failed, hapPath: %{private}s.", hapPath.c_str());
113 continue;
114 }
115 readSuccess = true;
116 }
117 return readSuccess;
118 }
119
ParseComponentCollectionJson( const std::string& bundleName, const std::string& content, std::unordered_set<std::string>& formModuleList, bool isReloadCondition)120 bool FormModulePreloader::ParseComponentCollectionJson(
121 const std::string& bundleName, const std::string& content,
122 std::unordered_set<std::string>& formModuleList, bool isReloadCondition)
123 {
124 auto collectionJson = JsonUtil::ParseJsonString(content);
125 if (collectionJson == nullptr || collectionJson->IsNull()) {
126 TAG_LOGW(AceLogTag::ACE_FORM, "Parse component_collection.json failed");
127 return false;
128 }
129 for (auto child = collectionJson->GetChild(); child && !child->IsNull(); child = child->GetNext()) {
130 std::string etsPath = child->GetKey();
131 auto item = collectionJson->GetValue(etsPath);
132 if (item == nullptr || !item->IsValid() || !item->IsArray()) {
133 TAG_LOGW(
134 AceLogTag::ACE_FORM, "Parse component_collection.json failed, etsPath: %{private}s.", etsPath.c_str());
135 return false;
136 }
137 int32_t len = item->GetArraySize();
138 for (int32_t index = 0; index < len; ++index) {
139 auto component = item->GetArrayItem(index);
140 if (component == nullptr || !component->IsString()) {
141 TAG_LOGW(AceLogTag::ACE_FORM, "Read view failed, etsPath: %{private}s.", etsPath.c_str());
142 return false;
143 }
144 std::string componentName = component->GetString();
145 if (!isReloadCondition) {
146 formModuleList.emplace(componentName);
147 continue;
148 }
149 std::lock_guard<std::mutex> lock(gMapLock_);
150 auto& iter = gFormModuleMap_[bundleName];
151 if (iter.find(componentName) == iter.end()) {
152 formModuleList.emplace(componentName);
153 iter.emplace(bundleName);
154 }
155 }
156 }
157 return true;
158 }
159
ReadFileFromAssetManager( const RefPtr<AssetManager>& assetManager, const std::string& fileName, std::string& content)160 bool FormModulePreloader::ReadFileFromAssetManager(
161 const RefPtr<AssetManager>& assetManager, const std::string& fileName, std::string& content)
162 {
163 if (assetManager == nullptr) {
164 TAG_LOGW(AceLogTag::ACE_FORM, "assetManager is null.");
165 return false;
166 }
167 auto jsAsset = assetManager->GetAsset(fileName);
168 if (jsAsset == nullptr) {
169 TAG_LOGW(AceLogTag::ACE_FORM, "uri: %{private}s Asset is null", fileName.c_str());
170 return false;
171 }
172 auto bufLen = jsAsset->GetSize();
173 auto buffer = jsAsset->GetData();
174 if ((buffer == nullptr) || (bufLen <= 0)) {
175 TAG_LOGW(AceLogTag::ACE_FORM, "uri: %{private}s buffer is null", fileName.c_str());
176 return false;
177 }
178 content.assign(buffer, buffer + bufLen);
179 return true;
180 }
181
CreateAssetManager(const std::string& hapPath)182 RefPtr<AssetManager> FormModulePreloader::CreateAssetManager(const std::string& hapPath)
183 {
184 std::vector<std::string> basePaths;
185 basePaths.emplace_back("");
186 basePaths.emplace_back("ets/");
187 basePaths.emplace_back("ets/widget/");
188 basePaths.emplace_back("resources/base/profile/");
189 RefPtr<AssetManager> assetManager = Referenced::MakeRefPtr<AssetManagerImpl>();
190 if (assetManager == nullptr) {
191 TAG_LOGW(AceLogTag::ACE_FORM, "Create AssetManagerImpl failed.");
192 return nullptr;
193 }
194 auto assetProvider = CreateAssetProviderImpl(hapPath, basePaths, false);
195 if (assetProvider == nullptr) {
196 TAG_LOGW(AceLogTag::ACE_FORM, "CreateAssetProvider failed.");
197 return nullptr;
198 }
199 assetManager->PushBack(std::move(assetProvider));
200 return assetManager;
201 }
202 } // namespace OHOS::Ace
203