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