• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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