• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "core/components_ng/pattern/plugin/plugin_pattern.h"
17 
18 #include <string>
19 
20 #ifdef OS_ACCOUNT_EXISTS
21 #include "os_account_manager.h"
22 #endif // OS_ACCOUNT_EXISTS
23 
24 #include "base/log/log_wrapper.h"
25 #include "base/utils/utils.h"
26 #include "core/common/plugin_manager.h"
27 #include "core/components/plugin/plugin_component_manager.h"
28 #include "core/components/plugin/plugin_sub_container.h"
29 #include "core/components/plugin/render_plugin.h"
30 #include "core/components/plugin/resource/plugin_manager_delegate.h"
31 #include "core/components_ng/pattern/plugin/plugin_event_hub.h"
32 #include "core/components_ng/render/adapter/rosen_render_context.h"
33 
34 namespace OHOS::Ace::NG {
35 namespace {
36 #ifndef OS_ACCOUNT_EXISTS
37 constexpr int32_t DEFAULT_OS_ACCOUNT_ID = 0; // 0 is the default id when there is no os_account part
38 #endif                                       // OS_ACCOUNT_EXISTS
39 
GetActiveAccountIds(std::vector<int32_t> & userIds)40 ErrCode GetActiveAccountIds(std::vector<int32_t>& userIds)
41 {
42     userIds.clear();
43 #ifdef OS_ACCOUNT_EXISTS
44     return AccountSA::OsAccountManager::QueryActiveOsAccountIds(userIds);
45 #else  // OS_ACCOUNT_EXISTS
46     userIds.push_back(DEFAULT_OS_ACCOUNT_ID);
47     return ERR_OK;
48 #endif // OS_ACCOUNT_EXISTS
49 }
50 constexpr char JS_EXT[] = ".js";
51 constexpr char ETS_EXT[] = ".ets";
52 constexpr size_t SIZE_OF_ETS_EXT = 4;
53 } // namespace
54 
~PluginPattern()55 PluginPattern::~PluginPattern()
56 {
57     pluginManagerBridge_.Reset();
58     if (pluginSubContainer_) {
59         auto currentId = pluginSubContainer_->GetInstanceId();
60         PluginManager::GetInstance().RemovePluginSubContainer(currentId);
61         PluginManager::GetInstance().RemovePluginParentContainer(currentId);
62         pluginSubContainer_->Destroy();
63         pluginSubContainer_.Reset();
64     }
65 }
66 
OnAttachToFrameNode()67 void PluginPattern::OnAttachToFrameNode()
68 {
69     auto host = GetHost();
70     CHECK_NULL_VOID(host);
71     host->GetRenderContext()->SetClipToFrame(true);
72     InitPluginManagerDelegate();
73 }
74 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)75 bool PluginPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
76 {
77     if (config.skipMeasure && config.skipLayout) {
78         return false;
79     }
80 
81     auto size = dirty->GetGeometryNode()->GetFrameSize();
82     auto host = GetHost();
83     CHECK_NULL_RETURN(host, false);
84     auto layoutProperty = host->GetLayoutProperty<PluginLayoutProperty>();
85     CHECK_NULL_RETURN(layoutProperty, false);
86     auto info = layoutProperty->GetRequestPluginInfo().value_or(RequestPluginInfo());
87     info.width = Dimension(size.Width());
88     info.height = Dimension(size.Height());
89     layoutProperty->UpdateRequestPluginInfo(info);
90     auto data = layoutProperty->GetData().value_or("");
91     if (info.bundleName != pluginInfo_.bundleName || info.abilityName != pluginInfo_.abilityName ||
92         info.moduleName != pluginInfo_.moduleName || info.pluginName != pluginInfo_.pluginName ||
93         info.dimension != pluginInfo_.dimension || data_ != data) {
94         pluginInfo_ = info;
95         data_ = data;
96     } else {
97         // for update pluguin component
98         if (pluginInfo_.allowUpdate != info.allowUpdate) {
99             pluginInfo_.allowUpdate = info.allowUpdate;
100             if (pluginSubContainer_) {
101                 pluginSubContainer_->SetAllowUpdate(pluginInfo_.allowUpdate);
102             }
103         }
104 
105         if (pluginInfo_.width != info.width || pluginInfo_.height != info.height) {
106             pluginInfo_.width = info.width;
107             pluginInfo_.height = info.height;
108             if (pluginSubContainer_) {
109                 pluginSubContainer_->SetPluginPattern(WeakClaim(this));
110                 pluginSubContainer_->UpdateRootElementSize();
111                 pluginSubContainer_->UpdateSurfaceSize();
112             }
113         }
114         return false;
115     }
116     loadFialState_ = false;
117     CreatePluginSubContainer();
118     if (pluginManagerBridge_) {
119         pluginManagerBridge_->AddPlugin(host->GetContext(), info);
120     }
121     return false;
122 }
123 
InitPluginManagerDelegate()124 void PluginPattern::InitPluginManagerDelegate()
125 {
126     CHECK_NULL_VOID(!pluginManagerBridge_);
127     auto host = GetHost();
128     CHECK_NULL_VOID(host);
129     auto context = host->GetContext();
130     CHECK_NULL_VOID(context);
131     pluginManagerBridge_ = AceType::MakeRefPtr<PluginManagerDelegate>(context);
132     int32_t instanceID = context->GetInstanceId();
133     pluginManagerBridge_->AddPluginCompleteCallback([weak = WeakClaim(this), instanceID]() {
134         ContainerScope scope(instanceID);
135         auto plugin = weak.Upgrade();
136         CHECK_NULL_VOID(plugin);
137         auto host = plugin->GetHost();
138         CHECK_NULL_VOID(host);
139         auto uiTaskExecutor =
140             SingleTaskExecutor::Make(host->GetContext()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
141         uiTaskExecutor.PostTask([weak, instanceID] {
142             ContainerScope scope(instanceID);
143             auto plugin = weak.Upgrade();
144             CHECK_NULL_VOID(plugin);
145             plugin->FireOnCompleteEvent();
146         });
147     });
148     pluginManagerBridge_->AddPluginUpdateCallback([weak = WeakClaim(this), instanceID](int64_t id, std::string data) {
149         ContainerScope scope(instanceID);
150         auto plugin = weak.Upgrade();
151         CHECK_NULL_VOID(plugin);
152         auto host = plugin->GetHost();
153         CHECK_NULL_VOID(host);
154         auto uiTaskExecutor =
155             SingleTaskExecutor::Make(host->GetContext()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
156         uiTaskExecutor.PostTask([id, data, weak] {
157             auto plugin = weak.Upgrade();
158             CHECK_NULL_VOID(plugin);
159             plugin->GetPluginSubContainer()->UpdatePlugin(data);
160         });
161     });
162     pluginManagerBridge_->AddPluginErrorCallback(
163         [weak = WeakClaim(this), instanceID](std::string code, std::string msg) {
164             ContainerScope scope(instanceID);
165             auto plugin = weak.Upgrade();
166             CHECK_NULL_VOID(plugin);
167             auto host = plugin->GetHost();
168             CHECK_NULL_VOID(host);
169             auto uiTaskExecutor =
170                 SingleTaskExecutor::Make(host->GetContext()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
171             uiTaskExecutor.PostTask([code, msg, weak, instanceID] {
172                 ContainerScope scope(instanceID);
173                 auto plugin = weak.Upgrade();
174                 CHECK_NULL_VOID(plugin);
175                 plugin->FireOnErrorEvent(code, msg);
176             });
177         });
178 }
179 
CreatePluginSubContainer()180 void PluginPattern::CreatePluginSubContainer()
181 {
182     auto host = GetHost();
183     CHECK_NULL_VOID(host);
184     auto context = host->GetContext();
185     CHECK_NULL_VOID(context);
186     auto layoutProperty = host->GetLayoutProperty<PluginLayoutProperty>();
187     CHECK_NULL_VOID(layoutProperty);
188 
189     auto parentcontainerId = Container::CurrentId();
190     while (parentcontainerId >= MIN_PLUGIN_SUBCONTAINER_ID) {
191         parentcontainerId = PluginManager::GetInstance().GetPluginParentContainerId(parentcontainerId);
192     }
193 
194     if (pluginSubContainer_) {
195         auto currentId = pluginSubContainer_->GetInstanceId();
196         PluginManager::GetInstance().RemovePluginSubContainer(currentId);
197         PluginManager::GetInstance().RemovePluginParentContainer(currentId);
198         pluginSubContainer_->Destroy();
199         pluginSubContainer_.Reset();
200     }
201     auto pluginSubContainerId_ = PluginManager::GetInstance().GetPluginSubContainerId();
202     pluginSubContainer_ = AceType::MakeRefPtr<PluginSubContainer>(context, pluginSubContainerId_);
203     CHECK_NULL_VOID(pluginSubContainer_);
204 
205     PluginManager::GetInstance().AddPluginSubContainer(pluginSubContainerId_, pluginSubContainer_);
206     PluginManager::GetInstance().AddPluginParentContainer(pluginSubContainerId_, parentcontainerId);
207     pluginSubContainer_->Initialize();
208     auto weak = WeakClaim(this);
209     pluginSubContainer_->SetPluginPattern(weak);
210     auto pattern = weak.Upgrade();
211     auto host_ = pattern->GetHost();
212     CHECK_NULL_VOID(host_);
213     pluginSubContainer_->SetPluginWindowId(GetHost()->GetId());
214     pluginSubContainer_->SetPluginNode(GetHost());
215 
216     auto uiTaskExecutor = SingleTaskExecutor::Make(host_->GetContext()->GetTaskExecutor(), TaskExecutor::TaskType::UI);
217 
218     int32_t instanceID = context->GetInstanceId();
219     uiTaskExecutor.PostTask([weak, instanceID] {
220         ContainerScope scope(instanceID);
221         auto pluginPattern = weak.Upgrade();
222         CHECK_NULL_VOID(pluginPattern);
223         auto pluginSubContainer = pluginPattern->GetPluginSubContainer();
224         RequestPluginInfo info = pluginPattern->GetPluginRequestInfo();
225         CHECK_NULL_VOID(pluginSubContainer);
226         auto packagePathStr = pluginPattern->GetPackagePath(weak, info);
227         if (packagePathStr.empty()) {
228             pluginPattern->FireOnErrorEvent("1", "package path is empty.");
229             return;
230         }
231         if (!info.bundleName.empty() && !info.moduleName.empty()) {
232             pluginPattern->pluginSubContainer_->SetPluginBundleName(info.bundleName);
233             pluginPattern->pluginSubContainer_->SetPluginModuleName(info.moduleName);
234         }
235         if (packagePathStr.rfind(".hap") != std::string::npos) {
236             std::string sub = packagePathStr.substr(1, packagePathStr.size() - 5) + "/";
237             pluginPattern->ReplaceAll(info.source, sub, "");
238             pluginPattern->pluginSubContainer_->RunDecompressedPlugin(
239                 packagePathStr, info.abilityName, info.source, info.moduleResPath, pluginPattern->GetData());
240         } else {
241             pluginPattern->pluginSubContainer_->RunPlugin(
242                 packagePathStr, info.abilityName, info.source, info.moduleResPath, pluginPattern->GetData());
243         }
244     });
245 }
246 
ReplaceAll(std::string & str,const std::string & pattern,const std::string & newPattern)247 void PluginPattern::ReplaceAll(std::string& str, const std::string& pattern, const std::string& newPattern)
248 {
249     const size_t nSize = newPattern.size();
250     const size_t pSize = pattern.size();
251     for (size_t pos = str.find(pattern, 0); pos != std::string::npos; pos = str.find(pattern, pos + nSize)) {
252         str.replace(pos, pSize, newPattern);
253     }
254 }
255 
GetDrawDelegate()256 std::unique_ptr<DrawDelegate> PluginPattern::GetDrawDelegate()
257 {
258     auto drawDelegate = std::make_unique<DrawDelegate>();
259 #ifdef ENABLE_ROSEN_BACKEND
260     drawDelegate->SetDrawRSFrameCallback(
261         [weak = WeakClaim(this)](std::shared_ptr<RSNode>& node, const Rect& /* dirty */) {
262             auto plugin = weak.Upgrade();
263             CHECK_NULL_VOID(plugin);
264             auto host = plugin->GetHost();
265             CHECK_NULL_VOID(host);
266             auto context = DynamicCast<NG::RosenRenderContext>(host->GetRenderContext());
267             CHECK_NULL_VOID(context);
268             auto rsNode = context->GetRSNode();
269             CHECK_NULL_VOID(rsNode);
270             if (node) {
271                 node->SetBackgroundColor(Color::TRANSPARENT.GetValue());
272             }
273             rsNode->AddChild(node, -1);
274             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
275         });
276 #endif
277     return drawDelegate;
278 }
279 
FireOnCompleteEvent() const280 void PluginPattern::FireOnCompleteEvent() const
281 {
282     if (loadFialState_) {
283         return;
284     }
285     auto host = GetHost();
286     CHECK_NULL_VOID(host);
287     auto eventHub = host->GetEventHub<PluginEventHub>();
288     CHECK_NULL_VOID(eventHub);
289     auto json = JsonUtil::Create(true);
290     eventHub->FireOnComplete(json->ToString());
291 }
292 
FireOnErrorEvent(const std::string & code,const std::string & msg)293 void PluginPattern::FireOnErrorEvent(const std::string& code, const std::string& msg)
294 {
295     loadFialState_ = true;
296     TAG_LOGD(AceLogTag::ACE_PLUGIN_COMPONENT, "code: %{public}s, msg: %{public}s", code.c_str(), msg.c_str());
297     auto host = GetHost();
298     CHECK_NULL_VOID(host);
299     auto eventHub = host->GetEventHub<PluginEventHub>();
300     CHECK_NULL_VOID(eventHub);
301     auto json = JsonUtil::Create(true);
302     json->Put("errcode", code.c_str());
303     json->Put("msg", msg.c_str());
304     eventHub->FireOnError(json->ToString());
305 }
306 
OnActionEvent(const std::string & action) const307 void PluginPattern::OnActionEvent(const std::string& action) const
308 {
309     TAG_LOGD(AceLogTag::ACE_PLUGIN_COMPONENT, "action: %{public}s", action.c_str());
310     auto eventAction = JsonUtil::ParseJsonString(action);
311     if (!eventAction->IsValid()) {
312         return;
313     }
314     auto actionType = eventAction->GetValue("action");
315     if (!actionType->IsValid()) {
316         return;
317     }
318 
319     auto type = actionType->GetString();
320     if (type != "router" && type != "message") {
321         return;
322     }
323 
324     CHECK_NULL_VOID(pluginManagerBridge_);
325     pluginManagerBridge_->OnActionEvent(action);
326 }
327 
ISAllowUpdate() const328 bool PluginPattern::ISAllowUpdate() const
329 {
330     auto host = GetHost();
331     CHECK_NULL_RETURN(host, true);
332     auto property = host->GetLayoutProperty<PluginLayoutProperty>();
333     CHECK_NULL_RETURN(property, true);
334     auto pluginInfo = property->GetRequestPluginInfo();
335     CHECK_NULL_RETURN(property, true);
336     return pluginInfo->allowUpdate;
337 }
338 
SplitString(const std::string & str,char tag,std::vector<std::string> & strList) const339 void PluginPattern::SplitString(const std::string& str, char tag, std::vector<std::string>& strList) const
340 {
341     std::string subStr;
342     for (size_t i = 0; i < str.length(); i++) {
343         if (tag == str[i]) {
344             if (!subStr.empty()) {
345                 strList.push_back(subStr);
346                 subStr.clear();
347             }
348         } else {
349             subStr.push_back(str[i]);
350         }
351     }
352     if (!subStr.empty()) {
353         strList.push_back(subStr);
354     }
355 }
356 
GetPackagePath(const WeakPtr<PluginPattern> & weak,RequestPluginInfo & info) const357 std::string PluginPattern::GetPackagePath(const WeakPtr<PluginPattern>& weak, RequestPluginInfo& info) const
358 {
359     std::string packagePathStr;
360     size_t pos_ets = info.pluginName.rfind(ETS_EXT);
361     if (pos_ets != std::string::npos && info.pluginName.substr(pos_ets) == ETS_EXT) {
362         info.pluginName = info.pluginName.substr(0, info.pluginName.length() - SIZE_OF_ETS_EXT);
363         info.pluginName = info.pluginName + JS_EXT;
364     }
365     size_t pos = info.pluginName.rfind(JS_EXT);
366     if (info.pluginName.front() == '/' && pos != std::string::npos && info.pluginName.substr(pos) == JS_EXT) {
367         packagePathStr = GetPackagePathByAbsolutePath(weak, info);
368     } else {
369         packagePathStr = GetPackagePathByWant(weak, info);
370     }
371     return packagePathStr;
372 }
373 
GetPackagePathByWant(const WeakPtr<PluginPattern> & weak,RequestPluginInfo & info) const374 std::string PluginPattern::GetPackagePathByWant(const WeakPtr<PluginPattern>& weak, RequestPluginInfo& info) const
375 {
376     std::string packagePathStr;
377     auto pluginPattern = weak.Upgrade();
378     CHECK_NULL_RETURN(pluginPattern, packagePathStr);
379     std::vector<std::string> strList;
380     pluginPattern->SplitString(info.bundleName, '/', strList);
381 
382     std::vector<int32_t> userIds;
383     ErrCode errCode = GetActiveAccountIds(userIds);
384     if (errCode != ERR_OK) {
385         pluginPattern->FireOnErrorEvent("1", "Query Active OsAccountIds failed!");
386         return packagePathStr;
387     }
388     GetAbilityNameByWant(weak, info);
389     packagePathStr = GerPackagePathByBms(weak, info, strList, userIds);
390 
391     return packagePathStr;
392 }
GetPackagePathByAbsolutePath(const WeakPtr<PluginPattern> & weak,RequestPluginInfo & info) const393 std::string PluginPattern::GetPackagePathByAbsolutePath(
394     const WeakPtr<PluginPattern>& weak, RequestPluginInfo& info) const
395 {
396     std::string packagePathStr;
397     auto pluginPattern = weak.Upgrade();
398     CHECK_NULL_RETURN(pluginPattern, packagePathStr);
399     std::string assets = "assets/js/";
400     size_t posAssets = info.pluginName.rfind(assets);
401     if (posAssets != std::string::npos) {
402         packagePathStr = info.pluginName.substr(0, posAssets);
403         size_t posModule = info.pluginName.find("/", posAssets + assets.size());
404         if (posModule != std::string::npos) {
405             info.abilityName =
406                 info.pluginName.substr(posAssets + assets.size(), posModule - (posAssets + assets.size()));
407             info.source = info.pluginName.substr(posModule);
408         } else {
409             info.abilityName = "/";
410             info.source = info.pluginName.substr(posAssets + assets.size());
411         }
412     } else {
413         size_t pos = info.pluginName.rfind("/");
414         packagePathStr = info.pluginName.substr(0, pos + 1);
415         info.source = info.pluginName.substr(pos + 1);
416         info.abilityName = "/";
417     }
418     return packagePathStr;
419 }
420 
GetAbilityNameByWant(const WeakPtr<PluginPattern> & weak,RequestPluginInfo & info) const421 void PluginPattern::GetAbilityNameByWant(const WeakPtr<PluginPattern>& weak, RequestPluginInfo& info) const
422 {
423     auto pluginPattern = weak.Upgrade();
424     CHECK_NULL_VOID(pluginPattern);
425     std::vector<std::string> strList;
426     pluginPattern->SplitString(info.pluginName, '&', strList);
427     if (strList.empty()) {
428         pluginPattern->FireOnErrorEvent("1", "Template source is empty.");
429         return;
430     }
431     if (strList.size() == 1) {
432         auto pos = info.pluginName.rfind(JS_EXT);
433         if (pos != std::string::npos && (strList[0].substr(pos) == JS_EXT)) {
434             info.source = info.pluginName;
435         } else {
436             info.abilityName = info.pluginName;
437         }
438     } else {
439         size_t pos_ets = strList[0].rfind(ETS_EXT);
440         if (pos_ets != std::string::npos && strList[0].substr(pos_ets) == ETS_EXT) {
441             strList[0] = strList[0].substr(0, strList[0].length() - SIZE_OF_ETS_EXT);
442             strList[0] = strList[0] + JS_EXT;
443         }
444         auto pos = strList[0].rfind(JS_EXT);
445         if (pos != std::string::npos && (strList[0].substr(pos) == JS_EXT)) {
446             info.source = strList[0];
447         } else {
448             info.abilityName = strList[0];
449         }
450         info.moduleName = strList[1];
451     }
452 }
453 
GerPackagePathByBms(const WeakPtr<PluginPattern> & weak,RequestPluginInfo & info,const std::vector<std::string> & strList,const std::vector<int32_t> & userIds) const454 std::string PluginPattern::GerPackagePathByBms(const WeakPtr<PluginPattern>& weak, RequestPluginInfo& info,
455     const std::vector<std::string>& strList, const std::vector<int32_t>& userIds) const
456 {
457     std::string packagePathStr;
458     auto pluginPattern = weak.Upgrade();
459     CHECK_NULL_RETURN(pluginPattern, packagePathStr);
460     auto bms = PluginComponentManager::GetInstance()->GetBundleManager();
461     if (!bms) {
462         pluginPattern->FireOnErrorEvent("1", "Bms bundleManager is nullptr.");
463         return packagePathStr;
464     }
465 
466     if (strList.empty()) {
467         pluginPattern->FireOnErrorEvent("1", "App bundleName is empty.");
468         return packagePathStr;
469     }
470 
471     AppExecFwk::BundleInfo bundleInfo;
472     bool ret = bms->GetBundleInfo(strList[0], AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo,
473         userIds.size() > 0 ? userIds[0] : AppExecFwk::Constants::UNSPECIFIED_USERID);
474     if (!ret) {
475         pluginPattern->FireOnErrorEvent("1", "Bms get bundleName failed!");
476         return packagePathStr;
477     }
478     if (bundleInfo.hapModuleInfos.empty() || bundleInfo.hapModuleInfos[0].hapPath.empty()) {
479         if (strList.size() == 1) {
480             if (bundleInfo.moduleResPaths.size() == 1) {
481                 info.moduleResPath = bundleInfo.moduleResPaths[0];
482             } else {
483                 pluginPattern->FireOnErrorEvent("1", "Bms moduleResPaths is empty.");
484                 return packagePathStr;
485             }
486             packagePathStr = bundleInfo.moduleDirs[0] + "/";
487         } else {
488             AAFwk::Want want;
489             AppExecFwk::AbilityInfo abilityInfo;
490             AppExecFwk::ElementName element("", strList[0], strList[1]);
491             want.SetElement(element);
492             bool ret = bms->QueryAbilityInfo(want, AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT,
493                 userIds.size() > 0 ? userIds[0] : AppExecFwk::Constants::UNSPECIFIED_USERID, abilityInfo);
494             if (!ret) {
495                 pluginPattern->FireOnErrorEvent("1", "Bms get bundleName failed!");
496                 return packagePathStr;
497             }
498             packagePathStr = abilityInfo.applicationInfo.codePath + "/" + abilityInfo.package + "/";
499             info.moduleResPath = abilityInfo.resourcePath;
500         }
501         return packagePathStr;
502     }
503     if (info.moduleName.empty() || info.moduleName == "default") {
504         info.moduleResPath = bundleInfo.hapModuleInfos[0].resourcePath;
505         info.moduleName = bundleInfo.hapModuleInfos[0].name;
506         packagePathStr = bundleInfo.hapModuleInfos[0].hapPath;
507         return packagePathStr;
508     }
509     auto result = std::find_if(bundleInfo.hapModuleInfos.begin(), bundleInfo.hapModuleInfos.end(),
510         [moduleName = info.moduleName](
511             AppExecFwk::HapModuleInfo hapModuleInfo) { return hapModuleInfo.moduleName == moduleName; });
512     if (result != bundleInfo.hapModuleInfos.end()) {
513         info.moduleResPath = result->resourcePath;
514         packagePathStr = result->hapPath;
515         return packagePathStr;
516     }
517     pluginPattern->FireOnErrorEvent(
518         "1", "Bms get hapPath failed! Cannot find hap according to BundleName and ModuleName!");
519     return packagePathStr;
520 }
521 
GetPluginSubContainer() const522 const RefPtr<PluginSubContainer>& PluginPattern::GetPluginSubContainer() const
523 {
524     return pluginSubContainer_;
525 };
526 
FlushReload() const527 void PluginPattern::FlushReload() const
528 {
529     auto host = GetHost();
530     CHECK_NULL_VOID(host);
531     auto customNode = DynamicCast<CustomNodeBase>(host->GetFirstChild());
532     CHECK_NULL_VOID(customNode);
533     customNode->FireReloadFunction(true);
534 }
535 } // namespace OHOS::Ace::NG
536