1 /*
2 * Copyright (c) 2021-2022 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 "core/components/plugin/plugin_component_manager.h"
17
18 #include <map>
19 #include <vector>
20
21 #include "iservice_registry.h"
22 #include "system_ability_definition.h"
23 #include "ui_service_mgr_client.h"
24
25 #include "base/json/json_util.h"
26 #include "base/log/log.h"
27
28 namespace OHOS::Ace {
29 constexpr int64_t FOO_MAX_LEN = 20 * 1024 * 1024;
30 std::shared_ptr<PluginComponentManager> PluginComponentManager::instance_ = nullptr;
31 std::mutex PluginComponentManager::mutex_;
32
GetInstance()33 std::shared_ptr<PluginComponentManager> PluginComponentManager::GetInstance()
34 {
35 if (!instance_) {
36 std::lock_guard<std::mutex> lock(mutex_);
37 if (!instance_) {
38 instance_ = std::make_shared<PluginComponentManager>();
39 }
40 }
41 return instance_;
42 }
43
Push(const AAFwk::Want & want,const std::string & name,const std::string & jsonPath,const std::string & data,const std::string & extraData)44 int PluginComponentManager::Push(const AAFwk::Want& want, const std::string& name, const std::string& jsonPath,
45 const std::string& data, const std::string& extraData)
46 {
47 LOGD("PluginComponentManager::Push");
48 return Ace::UIServiceMgrClient::GetInstance()->Push(want, name, jsonPath, data, extraData);
49 }
50
Request(const AAFwk::Want & want,const std::string & name,const std::string & jsonPath,const std::string & data)51 int PluginComponentManager::Request(
52 const AAFwk::Want& want, const std::string& name, const std::string& jsonPath, const std::string& data)
53 {
54 LOGD("PluginComponentManager::Request: jsonPath=%{public}s", jsonPath.c_str());
55 if (jsonPath.empty()) {
56 return Ace::UIServiceMgrClient::GetInstance()->Request(want, name, data);
57 } else {
58 PluginComponentTemplate pluginTemplate;
59 // Read external.json(assets\external.json) or jsonPath
60 std::string jsonStr;
61 auto packagePathStr = GetPackagePath(want);
62 GetTemplatePathFromJsonFile(packagePathStr, name, jsonPath, jsonStr);
63 pluginTemplate.SetSource(jsonStr);
64 pluginTemplate.SetAbility(want.GetElement().GetBundleName() + "/" + want.GetElement().GetAbilityName());
65 if (listener_) {
66 listener_->RequestByJsonPath(pluginTemplate, data);
67 }
68 return 0;
69 }
70 }
71
ReturnRequest(const AAFwk::Want & want,const std::string & pluginName,const std::string & data,const std::string & extraData)72 int PluginComponentManager::ReturnRequest(
73 const AAFwk::Want& want, const std::string& pluginName, const std::string& data, const std::string& extraData)
74 {
75 LOGD("PluginComponentManager::ReturnRequest");
76 return Ace::UIServiceMgrClient::GetInstance()->ReturnRequest(want, pluginName, data, extraData);
77 }
78
RegisterCallBack(const AAFwk::Want & want,const std::shared_ptr<PluginComponentCallBack> & callback,CallBackType callBackType)79 void PluginComponentManager::RegisterCallBack(
80 const AAFwk::Want& want, const std::shared_ptr<PluginComponentCallBack>& callback, CallBackType callBackType)
81 {
82 LOGD("PluginComponentManager::RegisterCallBack");
83 if (listener_) {
84 listener_->ResgisterListener(callback, callBackType);
85 Ace::UIServiceMgrClient::GetInstance()->RegisterCallBack(want, listener_);
86 }
87 }
88
UnregisterCallBack(const AAFwk::Want & want)89 void PluginComponentManager::UnregisterCallBack(const AAFwk::Want& want)
90 {
91 Ace::UIServiceMgrClient::GetInstance()->UnregisterCallBack(want);
92 }
93
GetBundleManager()94 sptr<AppExecFwk::IBundleMgr> PluginComponentManager::GetBundleManager()
95 {
96 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
97 if (systemAbilityMgr == nullptr) {
98 LOGE("Failed to get SystemAbilityManager.");
99 return nullptr;
100 }
101
102 auto bundleObj = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
103 if (bundleObj == nullptr) {
104 LOGE("Failed to get bundle manager service");
105 return nullptr;
106 }
107
108 return iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
109 }
110
ResgisterListener(const std::shared_ptr<PluginComponentCallBack> & callback,CallBackType callBackType)111 void PluginComponentManager::UIServiceListener::ResgisterListener(
112 const std::shared_ptr<PluginComponentCallBack>& callback, CallBackType callBackType)
113 {
114 LOGD("PluginComponentManager::UIServiceListener::ResgisterListener");
115 std::lock_guard<std::recursive_mutex> lock(mutex_);
116 callbackVec_.try_emplace(callback, callBackType);
117 }
118
OnPushCallBack(const AAFwk::Want & want,const std::string & name,const std::string & jsonPath,const std::string & data,const std::string & extraData)119 void PluginComponentManager::UIServiceListener::OnPushCallBack(const AAFwk::Want& want,
120 const std::string& name, const std::string& jsonPath, const std::string& data, const std::string& extraData)
121 {
122 LOGD("PluginComponentManager::UIServiceListener::OnPushCallBack");
123 PluginComponentTemplate pluginTemplate;
124 if (!jsonPath.empty()) {
125 std::string jsonStr;
126 auto packagePathStr = PluginComponentManager::GetInstance()->GetPackagePath(want);
127 PluginComponentManager::GetInstance()->GetTemplatePathFromJsonFile(packagePathStr, name, jsonPath, jsonStr);
128 if (jsonStr.empty()) {
129 jsonStr = "{}";
130 }
131 pluginTemplate.SetSource(jsonStr);
132 } else {
133 pluginTemplate.SetSource(name);
134 }
135 pluginTemplate.SetAbility(want.GetElement().GetBundleName() + "/" + want.GetElement().GetAbilityName());
136
137 std::lock_guard<std::recursive_mutex> lock(mutex_);
138 for (auto &callback : callbackVec_) {
139 if (callback.second == CallBackType::PushEvent && callback.first != nullptr) {
140 callback.first->OnPushEvent(want, pluginTemplate, data, extraData);
141 }
142 }
143 }
144
OnRequestCallBack(const AAFwk::Want & want,const std::string & name,const std::string & data)145 void PluginComponentManager::UIServiceListener::OnRequestCallBack(
146 const AAFwk::Want& want, const std::string& name, const std::string& data)
147 {
148 LOGD("PluginComponentManager::UIServiceListener::OnRequestCallBack");
149 std::lock_guard<std::recursive_mutex> lock(mutex_);
150 for (auto &callback : callbackVec_) {
151 if (callback.second == CallBackType::RequestEvent && callback.first != nullptr) {
152 callback.first->OnRequestEvent(want, name, data);
153 }
154 }
155 }
156
OnReturnRequest(const AAFwk::Want & want,const std::string & source,const std::string & data,const std::string & extraData)157 void PluginComponentManager::UIServiceListener::OnReturnRequest(
158 const AAFwk::Want& want, const std::string& source, const std::string& data, const std::string& extraData)
159 {
160 LOGD("PluginComponentManager::UIServiceListener::OnReturnRequest");
161
162 std::vector<std::shared_ptr<PluginComponentCallBack>> callbacks;
163
164 {
165 std::lock_guard<std::recursive_mutex> lock(mutex_);
166 for (auto iter = callbackVec_.begin(); iter != callbackVec_.end();) {
167 if (iter->second == CallBackType::RequestCallBack && iter->first != nullptr) {
168 callbacks.emplace_back(iter->first);
169 callbackVec_.erase(iter++);
170 } else {
171 iter++;
172 }
173 }
174 }
175
176 PluginComponentTemplate pluginTemplate;
177 if (source.empty()) {
178 pluginTemplate.SetSource("{}");
179 } else {
180 pluginTemplate.SetSource(source);
181 }
182 pluginTemplate.SetAbility(want.GetElement().GetBundleName() + "/" + want.GetElement().GetAbilityName());
183
184 for (const auto& item : callbacks) {
185 item->OnRequestCallBack(pluginTemplate, data, extraData);
186 }
187 }
188
RequestByJsonPath(const PluginComponentTemplate & pluginTemplate,const std::string & data)189 void PluginComponentManager::UIServiceListener::RequestByJsonPath(
190 const PluginComponentTemplate& pluginTemplate, const std::string& data)
191 {
192 std::lock_guard<std::recursive_mutex> lock(mutex_);
193 for (auto iter = callbackVec_.begin(); iter != callbackVec_.end();) {
194 if (iter->second == CallBackType::RequestCallBack && iter->first != nullptr) {
195 iter->first->OnRequestCallBack(pluginTemplate, data, "{}");
196 callbackVec_.erase(iter++);
197 } else {
198 iter++;
199 }
200 }
201 }
202
GetTemplatePathFromJsonFile(const std::string & packagePathStr,const std::string & pluginName,const std::string & jsonPath,std::string & jsonStr)203 bool PluginComponentManager::GetTemplatePathFromJsonFile(
204 const std::string& packagePathStr, const std::string& pluginName, const std::string& jsonPath, std::string& jsonStr)
205 {
206 std::string external = std::string("/external.json");
207 auto externalPath = packagePathStr + external;
208 if (!jsonPath.empty()) {
209 externalPath = jsonPath;
210 }
211 char realPath[PATH_MAX] = { 0x00 };
212 if (realpath(externalPath.c_str(), realPath) == nullptr) {
213 LOGE("realpath fail! filePath: %{private}s, fail reason: %{public}s",
214 externalPath.c_str(), strerror(errno));
215 return false;
216 }
217 std::unique_ptr<FILE, decltype(&std::fclose)> file(std::fopen(realPath, "rb"), std::fclose);
218 if (!file) {
219 LOGE("open file failed, filePath: %{private}s, fail reason: %{public}s",
220 externalPath.c_str(), strerror(errno));
221 return false;
222 }
223 if (std::fseek(file.get(), 0, SEEK_END) != 0) {
224 LOGE("seek file tail error.");
225 return false;
226 }
227
228 int64_t size = std::ftell(file.get());
229 if (size == -1L || size == 0L || size > FOO_MAX_LEN) {
230 return false;
231 }
232 char* fileData = new (std::nothrow) char[size];
233 if (fileData == nullptr) {
234 LOGE("new json buff failed.");
235 return false;
236 }
237 rewind(file.get());
238 std::unique_ptr<char[]> jsonStream(fileData);
239 size_t result = std::fread(jsonStream.get(), 1, size, file.get());
240 if (result != (size_t)size) {
241 LOGE("read file failed.");
242 return false;
243 }
244
245 std::string jsonString(jsonStream.get(), jsonStream.get() + size);
246 if (pluginName.empty()) {
247 jsonStr = jsonString;
248 } else {
249 auto rootJson = JsonUtil::ParseJsonString(jsonString);
250 if (rootJson) {
251 jsonStr = rootJson->GetString(pluginName);
252 }
253 }
254
255 return true;
256 }
257
GetPackagePath(const AAFwk::Want & want) const258 std::string PluginComponentManager::GetPackagePath(const AAFwk::Want& want) const
259 {
260 std::string packagePathStr;
261
262 if (want.GetElement().GetBundleName().empty()) {
263 LOGE("App bundleName is empty.");
264 return packagePathStr;
265 }
266 auto bms = PluginComponentManager::GetInstance()->GetBundleManager();
267 if (!bms) {
268 LOGE("Bms bundleManager is nullptr.");
269 return packagePathStr;
270 }
271
272 if (want.GetElement().GetAbilityName().empty()) {
273 AppExecFwk::BundleInfo bundleInfo;
274 bool ret = bms->GetBundleInfo(
275 want.GetElement().GetBundleName(), AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo);
276 if (!ret) {
277 LOGE("Bms get bundleName failed!");
278 return packagePathStr;
279 }
280 packagePathStr = bundleInfo.applicationInfo.entryDir + "/";
281 } else {
282 AppExecFwk::AbilityInfo abilityInfo;
283 bool ret = bms->QueryAbilityInfo(want, abilityInfo);
284 if (!ret) {
285 LOGE("Bms get abilityInfo failed!");
286 return packagePathStr;
287 }
288 packagePathStr = abilityInfo.applicationInfo.codePath + "/" + abilityInfo.package + "/";
289 }
290 return packagePathStr;
291 }
292 } // namespace OHOS::Ace
293