support get other hap plugin

Signed-off-by: s30030188 <songjindian1@h-partners.com>
This commit is contained in:
s30030188
2025-06-12 21:37:20 +08:00
parent 9b801d1ddc
commit cbb0ee6c2f
8 changed files with 194 additions and 10 deletions
@@ -34,6 +34,7 @@ namespace {
constexpr size_t ARGC_ONE = 1;
constexpr size_t ARGC_TWO = 2;
constexpr size_t ARGC_THREE = 3;
constexpr size_t ARGC_FOUR = 4;
constexpr const char* PERMISSION_GET_BUNDLE_INFO = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED";
}
void JsApplication::Finalizer(napi_env env, void *data, void *hint)
@@ -81,6 +82,10 @@ napi_value JsApplication::CreatePluginModuleContext(napi_env env, napi_callback_
GET_NAPI_INFO_AND_CALL(env, info, JsApplication, OnCreatePluginModuleContext);
}
napi_value JsApplication::CreatePluginModuleContextForBundle(napi_env env, napi_callback_info info)
{
GET_NAPI_INFO_AND_CALL(env, info, JsApplication, OnCreatePluginModuleContextForBundle);
}
napi_value JsApplication::OnCreatePluginModuleContext(napi_env env, NapiCallbackInfo &info)
{
@@ -143,6 +148,89 @@ napi_value JsApplication::OnCreatePluginModuleContext(napi_env env, NapiCallback
return result;
}
napi_value JsApplication::OnCreatePluginModuleContextForBundle(napi_env env, NapiCallbackInfo &info)
{
std::string moduleName = "";
std::string pluginBundleName = "";
std::string hostBundleName = "";
if (!VerifyCreatePluginContextParams(env, info, moduleName, pluginBundleName, hostBundleName)) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid params");
return CreateJsUndefined(env);
}
bool stageMode = false;
napi_status status = OHOS::AbilityRuntime::IsStageContext(env, info.argv[ARGC_ZERO], stageMode);
if (status != napi_ok || !stageMode) {
ThrowInvalidParamError(env, "Parse param context failed, must be a context of stageMode.");
return CreateJsUndefined(env);
}
auto context = OHOS::AbilityRuntime::GetStageModeContext(env, info.argv[ARGC_ZERO]);
if (context == nullptr) {
ThrowInvalidParamError(env, "Parse param context failed, must not be nullptr.");
return CreateJsUndefined(env);
}
auto inputContextPtr = Context::ConvertTo<Context>(context);
if (inputContextPtr == nullptr) {
ThrowInvalidParamError(env, "Parse param context failed, must be a context.");
return CreateJsUndefined(env);
}
std::shared_ptr<std::shared_ptr<Context>> moduleContext = std::make_shared<std::shared_ptr<Context>>();
std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
if (contextImpl == nullptr) {
ThrowInvalidParamError(env, "create context failed.");
return CreateJsUndefined(env);
}
contextImpl->SetProcessName(context->GetProcessName());
TAG_LOGD(AAFwkTag::APPKIT, "moduleName: %{public}s, pluginBundleName: %{public}s, bundleName: %{public}s",
moduleName.c_str(), pluginBundleName.c_str(), hostBundleName.c_str());
NapiAsyncTask::ExecuteCallback execute = [moduleName, pluginBundleName, hostBundleName, contextImpl,
moduleContext, inputContextPtr]() {
if (contextImpl != nullptr) {
*moduleContext = contextImpl->CreateTargetPluginContext(
hostBundleName, pluginBundleName, moduleName, inputContextPtr);
}
};
NapiAsyncTask::CompleteCallback complete;
SetCreateCompleteCallback(moduleContext, complete);
napi_value result = nullptr;
NapiAsyncTask::ScheduleHighQos("JsApplication::OnCreatePluginModuleContext",
env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
return result;
}
bool JsApplication::VerifyCreatePluginContextParams(napi_env env, NapiCallbackInfo &info, std::string &moduleName,
std::string &pluginBundleName, std::string &hostBundleName)
{
if (info.argc != ARGC_FOUR) {
TAG_LOGE(AAFwkTag::APPKIT, "wrong number of params");
ThrowTooFewParametersError(env);
return false;
}
if (!ConvertFromJsValue(env, info.argv[ARGC_TWO], moduleName)
|| !ConvertFromJsValue(env, info.argv[ARGC_ONE], pluginBundleName)
|| !ConvertFromJsValue(env, info.argv[ARGC_THREE], hostBundleName)) {
ThrowInvalidParamError(env, "Parse param failed, moduleName and pluginBundleName must be string.");
return false;
}
if (!CheckCallerIsSystemApp()) {
TAG_LOGE(AAFwkTag::APPKIT, "no system app");
ThrowNotSystemAppError(env);
return false;
}
if (!CheckCallerPermission(PERMISSION_GET_BUNDLE_INFO)) {
TAG_LOGE(AAFwkTag::APPKIT, "no permission");
ThrowNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO);
return false;
}
return true;
}
napi_value JsApplication::OnCreateModuleContext(napi_env env, NapiCallbackInfo &info)
{
TAG_LOGD(AAFwkTag::APPKIT, "Called");
@@ -511,6 +599,9 @@ napi_value ApplicationInit(napi_env env, napi_value exportObj)
BindNativeFunction(env, exportObj, "demoteCurrentFromCandidateMasterProcess", moduleName,
JsApplication::DemoteCurrentFromCandidateMasterProcess);
BindNativeFunction(env, exportObj, "createPluginModuleContextForHostBundle", moduleName,
JsApplication::CreatePluginModuleContextForBundle);
return CreateJsUndefined(env);
}
} // namespace AbilityRuntime
@@ -37,11 +37,13 @@ public:
static napi_value CreatePluginModuleContext(napi_env env, napi_callback_info info);
static napi_value PromoteCurrentToCandidateMasterProcess(napi_env env, napi_callback_info info);
static napi_value DemoteCurrentFromCandidateMasterProcess(napi_env env, napi_callback_info info);
static napi_value CreatePluginModuleContextForBundle(napi_env env, napi_callback_info info);
private:
napi_value OnCreateModuleContext(napi_env env, NapiCallbackInfo &info);
napi_value OnCreateBundleContext(napi_env env, NapiCallbackInfo &info);
napi_value OnCreatePluginModuleContext(napi_env env, NapiCallbackInfo &info);
napi_value OnCreatePluginModuleContextForBundle(napi_env env, NapiCallbackInfo &info);
napi_value CreateJsContext(napi_env env, const std::shared_ptr<Context> &context);
void SetCreateCompleteCallback(std::shared_ptr<std::shared_ptr<Context>> contextPtr,
NapiAsyncTask::CompleteCallback &complete);
@@ -50,6 +52,8 @@ private:
napi_value OnGetApplicationContext(napi_env env, NapiCallbackInfo &info);
napi_value OnPromoteCurrentToCandidateMasterProcess(napi_env env, NapiCallbackInfo& info);
napi_value OnDemoteCurrentFromCandidateMasterProcess(napi_env env, NapiCallbackInfo& info);
bool VerifyCreatePluginContextParams(napi_env env, NapiCallbackInfo &info, std::string &moduleName,
std::string &pluginBundleName, std::string &hostBundleName);
};
napi_value ApplicationInit(napi_env env, napi_value exportObj);
@@ -1118,5 +1118,18 @@ ErrCode BundleMgrHelper::GetLauncherAbilityInfoSync(const std::string &bundleNam
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
return bundleMgr->GetLauncherAbilityInfoSync(bundleName, userId, abilityInfo);
}
ErrCode BundleMgrHelper::GetPluginInfoForTarget(const std::string &hostBundleName,
const std::string &pluginBundleName, int32_t userId, PluginBundleInfo &pluginBundleInfo)
{
TAG_LOGD(AAFwkTag::BUNDLEMGRHELPER, "called");
auto bundleMgr = Connect();
if (bundleMgr == nullptr) {
TAG_LOGE(AAFwkTag::BUNDLEMGRHELPER, "null bundleMgr");
return ERR_APPEXECFWK_SERVICE_INTERNAL_ERROR;
}
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
return bundleMgr->GetPluginInfo(hostBundleName, pluginBundleName, userId, pluginBundleInfo);
}
} // namespace AppExecFwk
} // namespace OHOS
@@ -485,7 +485,14 @@ std::shared_ptr<Context> ContextImpl::CreatePluginContext(const std::string &plu
return nullptr;
}
auto appContext = std::make_shared<ContextImpl>();
return WrapContext(pluginBundleName, moduleName, inputContext, pluginBundleInfo, inputContext->GetBundleName());
}
std::shared_ptr<Context> ContextImpl::WrapContext(const std::string &pluginBundleName, const std::string &moduleName,
std::shared_ptr<Context> inputContext, AppExecFwk::PluginBundleInfo& pluginBundleInfo,
const std::string &hostBundleName)
{
std::shared_ptr<ContextImpl> appContext = std::make_shared<ContextImpl>();
appContext->SetConfiguration(config_);
appContext->SetProcessName(processName_);
appContext->isPlugin_ = true;
@@ -499,7 +506,6 @@ std::shared_ptr<Context> ContextImpl::CreatePluginContext(const std::string &plu
if (resourceManager == nullptr) {
return nullptr;
}
for (auto pluginModuleInfo : pluginBundleInfo.pluginModuleInfos) {
TAG_LOGD(AAFwkTag::APPKIT, "moduleName: %{public}s", pluginModuleInfo.moduleName.c_str());
std::string loadPath = pluginModuleInfo.hapPath;
@@ -507,14 +513,24 @@ std::shared_ptr<Context> ContextImpl::CreatePluginContext(const std::string &plu
if (loadPath.empty()) {
continue;
}
std::regex pattern(std::string(ABS_CODE_PATH) + std::string(FILE_SEPARATOR) + inputContext->GetBundleName());
loadPath = std::regex_replace(loadPath, pattern, LOCAL_CODE_PATH);
bool newCreate = false;
std::shared_ptr<AbilityBase::Extractor> extractor =
AbilityBase::ExtractorUtil::GetExtractor(loadPath, newCreate, true);
if (!extractor) {
TAG_LOGE(AAFwkTag::APPKIT, "hapPath[%{private}s]", hapPath.c_str());
return nullptr;
if (moduleName != pluginModuleInfo.moduleName) {
TAG_LOGD(AAFwkTag::APPKIT, "not the target plugin");
continue;
}
if (inputContext->GetBundleName() == hostBundleName) {
std::regex pattern(
std::string(ABS_CODE_PATH) + std::string(FILE_SEPARATOR) + inputContext->GetBundleName());
loadPath = std::regex_replace(loadPath, pattern, LOCAL_CODE_PATH);
bool newCreate = false;
std::shared_ptr<AbilityBase::Extractor> extractor =
AbilityBase::ExtractorUtil::GetExtractor(loadPath, newCreate, true);
if (!extractor) {
TAG_LOGE(AAFwkTag::APPKIT, "hapPath[%{private}s]", hapPath.c_str());
return nullptr;
}
} else {
std::regex pattern(ABS_CODE_PATH);
loadPath = std::regex_replace(loadPath, pattern, LOCAL_BUNDLES);
}
TAG_LOGD(AAFwkTag::APPKIT, "loadPath: %{public}s", loadPath.c_str());
if (!resourceManager->AddResource(loadPath.c_str())) {
@@ -1798,5 +1814,40 @@ bool ContextImpl::GetDisplayConfig(uint64_t displayId, float &density, std::stri
return getDisplayConfigCallback_(displayId, density, directionStr);
}
#endif
std::shared_ptr<Context> ContextImpl::CreateTargetPluginContext(const std::string &hostBundName,
const std::string &pluginBundleName, const std::string &moduleName, std::shared_ptr<Context> inputContext)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
if (hostBundName.empty() || pluginBundleName.empty() || moduleName.empty() || inputContext == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "input params is null");
return nullptr;
}
TAG_LOGD(AAFwkTag::APPKIT, "hostBundName: %{public}s, pluginBundleName: %{public}s, moduleName: %{public}s",
hostBundName.c_str(), pluginBundleName.c_str(), moduleName.c_str());
int32_t errCode = GetBundleManager();
if (errCode != ERR_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "GetBundleManager failed, errCode: %{public}d", errCode);
return nullptr;
}
int accountId = GetCurrentAccountId();
if (accountId == 0) {
accountId = GetCurrentActiveAccountId();
}
if (bundleMgr_ == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null bundleMgr_");
return nullptr;
}
AppExecFwk::PluginBundleInfo pluginBundleInfo;
errCode = bundleMgr_->GetPluginInfoForTarget(hostBundName, pluginBundleName, accountId, pluginBundleInfo);
if (errCode != ERR_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "GetPluginInfosForTarget failed, errCode: %{public}d", errCode);
return nullptr;
}
return WrapContext(pluginBundleName, moduleName, inputContext, pluginBundleInfo, hostBundName);
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -32,11 +32,13 @@ public:
static napi_value CreateBundleContext(napi_env env, napi_callback_info info);
static napi_value GetApplicationContext(napi_env env, napi_callback_info info);
static napi_value CreatePluginModuleContext(napi_env env, napi_callback_info info);
static napi_value CreateOtherPluginModuleContext(napi_env env, napi_callback_info info);
private:
napi_value OnCreateModuleContext(napi_env env, NapiCallbackInfo &info);
napi_value OnCreateBundleContext(napi_env env, NapiCallbackInfo &info);
napi_value OnCreatePluginModuleContext(napi_env env, NapiCallbackInfo &info);
napi_value OnCreateOtherPluginModuleContext(napi_env env, NapiCallbackInfo &info);
napi_value CreateJsContext(napi_env env, const std::shared_ptr<Context> &context);
void SetCreateCompleteCallback(std::shared_ptr<std::shared_ptr<Context>> contextPtr,
NapiAsyncTask::CompleteCallback &complete);
@@ -125,6 +125,9 @@ public:
int32_t userId, BundleInfo &bundleInfo);
ErrCode GetLauncherAbilityInfoSync(const std::string &bundleName, int32_t userId,
std::vector<AbilityInfo> &abilityInfo);
ErrCode GetPluginInfoForTarget(const std::string &hostBundleName, const std::string &pluginBundleName,
int32_t userId, PluginBundleInfo &pluginBundleInfo);
private:
sptr<IBundleMgr> Connect();
sptr<IBundleMgr> Connect(bool checkBmsReady);
@@ -213,6 +213,9 @@ public:
std::shared_ptr<Context> CreatePluginContext(const std::string &pluginBundleName,
const std::string &moduleName, std::shared_ptr<Context> inputContext);
std::shared_ptr<Context> CreateTargetPluginContext(const std::string &hostBundName,
const std::string &pluginBundleName, const std::string &moduleName, std::shared_ptr<Context> inputContext);
std::string GetBundleNameWithContext(std::shared_ptr<Context> inputContext = nullptr) const;
/**
@@ -560,6 +563,9 @@ private:
static std::mutex getDisplayConfigCallbackMutex_;
static GetDisplayConfigCallback getDisplayConfigCallback_;
#endif
std::shared_ptr<Context> WrapContext(const std::string &pluginBundleName, const std::string &moduleName,
std::shared_ptr<Context> inputContext, AppExecFwk::PluginBundleInfo &pluginBundleInfo,
const std::string &hostBundleName);
};
} // namespace AbilityRuntime
} // namespace OHOS
@@ -99,5 +99,19 @@ HWTEST_F(BundleMgrHelperSecondTest, BundleMgrHelperSecondTest_GetDataDir_001, Te
auto ret = bundleMgrHelper->GetDataDir(bundleName, appIndex);
EXPECT_NE(ret, "");
}
/**
* @tc.name: BundleMgrHelperSecondTest_GetPluginInfoForTarget_001
* @tc.desc: GetDataDir
* @tc.type: FUNC
*/
HWTEST_F(BundleMgrHelperSecondTest, BundleMgrHelperSecondTest_GetPluginInfoForTarget_001, TestSize.Level1)
{
std::string hostBundleName = "hostBundleName";
std::string pluginBundleName = "pluginBundleName";
AppExecFwk::PluginBundleInfo pluginBundleInfo;
auto ret = bundleMgrHelper->GetPluginInfoForTarget(hostBundleName, pluginBundleName, 0, pluginBundleInfo);
EXPECT_NE(ret, ERR_OK);
}
} // namespace AppExecFwk
} // namespace OHOS