1 /*
2 * Copyright (c) 2025 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 #include "ets_application.h"
16
17 #include "ani_base_context.h"
18 #include "ani_common_util.h"
19 #include "application_context.h"
20 #include "application_context_manager.h"
21 #include "context_impl.h"
22 #include "ets_application_context_utils.h"
23 #include "ets_context_utils.h"
24 #include "ets_error_utils.h"
25 #include "hilog_tag_wrapper.h"
26 #include "permission_verification.h"
27
28 namespace OHOS {
29 namespace AbilityRuntime {
30 namespace {
31 constexpr const char* PERMISSION_GET_BUNDLE_INFO = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED";
32 constexpr const char* CONTEXT_CLASS_NAME = "Lapplication/Context/Context;";
33 constexpr const char* APPLICATION_SPACE_NAME = "L@ohos/app/ability/application/application;";
34 }
35
CreateEmptyContextObject(ani_env * env)36 ani_object CreateEmptyContextObject(ani_env *env)
37 {
38 ani_class cls = nullptr;
39 ani_status status = env->FindClass(CONTEXT_CLASS_NAME, &cls);
40 if (status != ANI_OK) {
41 TAG_LOGE(AAFwkTag::APPKIT, "find Context failed status: %{public}d", status);
42 return nullptr;
43 }
44 ani_method method = nullptr;
45 status = env->Class_FindMethod(cls, "<ctor>", ":V", &method);
46 if (status != ANI_OK) {
47 TAG_LOGE(AAFwkTag::APPKIT, "Class_FindMethod ctor failed status: %{public}d", status);
48 return nullptr;
49 }
50 ani_object objValue = nullptr;
51 if (env->Object_New(cls, method, &objValue) != ANI_OK) {
52 TAG_LOGE(AAFwkTag::APPKIT, "Object_New failed status: %{public}d", status);
53 return nullptr;
54 }
55 return objValue;
56 }
57
CheckIsSystemAppOrPermisson(ani_env * env,ani_object callback)58 bool CheckIsSystemAppOrPermisson(ani_env *env, ani_object callback)
59 {
60 auto emptyObject = CreateEmptyContextObject(env);
61 if (!AAFwk::PermissionVerification::GetInstance()->IsSystemAppCall()) {
62 TAG_LOGE(AAFwkTag::APPKIT, "no system app");
63 AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env,
64 static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP),
65 "The application is not system-app, can not use system-api."), emptyObject);
66 return false;
67 }
68 if (!AAFwk::PermissionVerification::GetInstance()->VerifyGetBundleInfoPrivilegedPermission()) {
69 TAG_LOGE(AAFwkTag::APPKIT, "no permission");
70 AppExecFwk::AsyncCallback(env, callback,
71 EtsErrorUtil::CreateNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO), emptyObject);
72 return false;
73 }
74 return true;
75 }
76
SetNativeContextLong(ani_env * env,std::shared_ptr<Context> context,ani_class & cls,ani_object & contextObj)77 bool SetNativeContextLong(ani_env *env, std::shared_ptr<Context> context, ani_class& cls, ani_object& contextObj)
78 {
79 if (env == nullptr || context == nullptr) {
80 TAG_LOGE(AAFwkTag::APPKIT, "env or context is null");
81 return false;
82 }
83 ani_status status = ANI_ERROR;
84 ani_method method {};
85 if ((status = env->Class_FindMethod(cls, "<ctor>", ":V", &method)) != ANI_OK) {
86 TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status);
87 return false;
88 }
89 if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) {
90 TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status);
91 return false;
92 }
93 ani_field field = nullptr;
94 if ((status = env->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) {
95 TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status);
96 return false;
97 }
98 auto workContext = new (std::nothrow) std::weak_ptr<Context>(context);
99 if (workContext == nullptr) {
100 TAG_LOGE(AAFwkTag::APPKIT, "workContext nullptr");
101 return false;
102 }
103 ani_long nativeContextLong = reinterpret_cast<ani_long>(workContext);
104 if (!ContextUtil::SetNativeContextLong(env, contextObj, nativeContextLong)) {
105 TAG_LOGE(AAFwkTag::APPKIT, "SetNativeContextLong failed");
106 delete workContext;
107 workContext = nullptr;
108 return false;
109 }
110 return true;
111 }
112
SetCreateCompleteCallback(ani_env * env,std::shared_ptr<std::shared_ptr<Context>> contextPtr,ani_object callback)113 void SetCreateCompleteCallback(ani_env *env, std::shared_ptr<std::shared_ptr<Context>> contextPtr, ani_object callback)
114 {
115 if (env == nullptr || contextPtr == nullptr) {
116 TAG_LOGE(AAFwkTag::APPKIT, "env or contextPtr is nullptr");
117 return;
118 }
119 auto context = *contextPtr;
120 if (!context) {
121 TAG_LOGE(AAFwkTag::APPKIT, "failed to create context");
122 auto emptyObject = CreateEmptyContextObject(env);
123 AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env,
124 AbilityErrorCode::ERROR_CODE_INVALID_PARAM), emptyObject);
125 return;
126 }
127 ani_class cls {};
128 ani_status status = ANI_ERROR;
129 if ((status = env->FindClass(CONTEXT_CLASS_NAME, &cls)) != ANI_OK) {
130 TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status);
131 return;
132 }
133 ani_object contextObj = nullptr;
134 if (!SetNativeContextLong(env, context, cls, contextObj)) {
135 TAG_LOGE(AAFwkTag::APPKIT, "set nativeContextLong failed");
136 return;
137 }
138 ContextUtil::CreateEtsBaseContext(env, cls, contextObj, context);
139 AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), contextObj);
140 }
141
GetContextByStageMode(ani_env * env,ani_object & contextObj,ani_object callback,ani_object emptyObject)142 std::shared_ptr<Context> GetContextByStageMode(ani_env *env, ani_object &contextObj,
143 ani_object callback, ani_object emptyObject)
144 {
145 ani_boolean stageMode = false;
146 ani_status status = IsStageContext(env, contextObj, stageMode);
147 if (status != ANI_OK || !stageMode) {
148 TAG_LOGE(AAFwkTag::APPKIT, "not stageMode");
149 AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env,
150 "Parse param context failed, must be a context of stageMode."), emptyObject);
151 return nullptr;
152 }
153 auto context = GetStageModeContext(env, contextObj);
154 if (context == nullptr) {
155 TAG_LOGE(AAFwkTag::APPKIT, "null context");
156 AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env,
157 "Parse param context failed, must not be nullptr."), emptyObject);
158 return nullptr;
159 }
160 return context;
161 }
162
CreateModuleContext(ani_env * env,ani_object contextObj,ani_string bundleName,ani_string moduleName,ani_object callback)163 void EtsApplication::CreateModuleContext(ani_env *env,
164 ani_object contextObj, ani_string bundleName, ani_string moduleName, ani_object callback)
165 {
166 TAG_LOGD(AAFwkTag::APPKIT, "CreateModuleContext Call");
167 if (env == nullptr) {
168 TAG_LOGE(AAFwkTag::APPKIT, "null env");
169 return;
170 }
171 ani_object emptyObject = CreateEmptyContextObject(env);
172 std::string stdBundleName = "";
173 std::string stdModuleName = "";
174 AppExecFwk::GetStdString(env, bundleName, stdBundleName);
175 AppExecFwk::GetStdString(env, moduleName, stdModuleName);
176 auto context = GetContextByStageMode(env, contextObj, callback, emptyObject);
177 if (context == nullptr) {
178 return;
179 }
180 auto inputContextPtr = Context::ConvertTo<Context>(context);
181 if (inputContextPtr == nullptr) {
182 TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed");
183 AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env,
184 "Parse param context failed, must be a context."), emptyObject);
185 return;
186 }
187 std::shared_ptr<std::shared_ptr<Context>> moduleContext = std::make_shared<std::shared_ptr<Context>>();
188 std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
189 if (contextImpl == nullptr) {
190 TAG_LOGE(AAFwkTag::APPKIT, "null contextImpl");
191 AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env,
192 "create context failed."), emptyObject);
193 return;
194 }
195 contextImpl->SetProcessName(context->GetProcessName());
196 if (stdBundleName.empty()) {
197 *moduleContext = contextImpl->CreateModuleContext(stdModuleName, inputContextPtr);
198 } else {
199 if (!CheckIsSystemAppOrPermisson(env, callback)) {
200 TAG_LOGE(AAFwkTag::APPKIT, "CheckCaller failed");
201 }
202 *moduleContext = contextImpl->CreateModuleContext(stdBundleName, stdModuleName, inputContextPtr);
203 }
204 SetCreateCompleteCallback(env, moduleContext, callback);
205 }
206
CreateBundleContext(ani_env * env,ani_object contextObj,ani_string bundleName,ani_object callback)207 void EtsApplication::CreateBundleContext(ani_env *env,
208 ani_object contextObj, ani_string bundleName, ani_object callback)
209 {
210 TAG_LOGD(AAFwkTag::APPKIT, "CreateBundleContext Call");
211 if (env == nullptr) {
212 TAG_LOGE(AAFwkTag::APPKIT, "null env");
213 return;
214 }
215 ani_object emptyObject = CreateEmptyContextObject(env);
216 if (!CheckIsSystemAppOrPermisson(env, callback)) {
217 TAG_LOGE(AAFwkTag::APPKIT, "CheckCaller failed");
218 return;
219 }
220 std::string stdBundleName = "";
221 AppExecFwk::GetStdString(env, bundleName, stdBundleName);
222 auto context = GetContextByStageMode(env, contextObj, callback, emptyObject);
223 if (context == nullptr) {
224 return;
225 }
226 auto inputContextPtr = Context::ConvertTo<Context>(context);
227 if (inputContextPtr == nullptr) {
228 TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed");
229 AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env,
230 "Parse param context failed, must be a context."), emptyObject);
231 return;
232 }
233 auto bundleContext = std::make_shared<std::shared_ptr<Context>>();
234 std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
235 if (contextImpl == nullptr) {
236 TAG_LOGE(AAFwkTag::APPKIT, "null contextImpl");
237 AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env,
238 "create context failed."), emptyObject);
239 return;
240 }
241 contextImpl->SetProcessName(context->GetProcessName());
242 contextImpl->CreateBundleContext(*bundleContext, stdBundleName, inputContextPtr);
243 SetCreateCompleteCallback(env, bundleContext, callback);
244 }
245
ApplicationInit(ani_env * env)246 void ApplicationInit(ani_env *env)
247 {
248 TAG_LOGD(AAFwkTag::APPKIT, "ApplicationInit Call");
249 if (env == nullptr) {
250 TAG_LOGE(AAFwkTag::APPKIT, "null env");
251 return;
252 }
253 ani_status status = ANI_ERROR;
254 ani_namespace ns;
255 status = env->FindNamespace(APPLICATION_SPACE_NAME, &ns);
256 if (status != ANI_OK) {
257 TAG_LOGE(AAFwkTag::APPKIT, "FindNamespace application failed status: %{public}d", status);
258 return;
259 }
260 std::array methods = {
261 ani_native_function {
262 "nativeCreateModuleContext",
263 "Lapplication/Context/Context;Lstd/core/String;Lstd/core/String;"
264 "Lutils/AbilityUtils/AsyncCallbackWrapper;:V",
265 reinterpret_cast<void *>(EtsApplication::CreateModuleContext)
266 },
267 ani_native_function {
268 "nativeCreateBundleContext",
269 "Lapplication/Context/Context;Lstd/core/String;"
270 "Lutils/AbilityUtils/AsyncCallbackWrapper;:V",
271 reinterpret_cast<void *>(EtsApplication::CreateBundleContext)
272 },
273 };
274 status = env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size());
275 if (status != ANI_OK) {
276 TAG_LOGE(AAFwkTag::APPKIT, "Namespace_BindNativeFunctions failed status: %{public}d", status);
277 }
278 }
279
280 extern "C" {
ANI_Constructor(ani_vm * vm,uint32_t * result)281 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
282 {
283 TAG_LOGD(AAFwkTag::APPKIT, "in ApplicationETS.ANI_Constructor");
284 if (vm == nullptr || result == nullptr) {
285 TAG_LOGE(AAFwkTag::APPKIT, "null vm or result");
286 return ANI_INVALID_ARGS;
287 }
288 ani_env *env = nullptr;
289 ani_status status = ANI_ERROR;
290 status = vm->GetEnv(ANI_VERSION_1, &env);
291 if (status != ANI_OK) {
292 TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed, status: %{public}d", status);
293 return ANI_NOT_FOUND;
294 }
295 ApplicationInit(env);
296 *result = ANI_VERSION_1;
297 TAG_LOGD(AAFwkTag::APPKIT, "AbilityManagerEts.ANI_Constructor finished");
298 return ANI_OK;
299 }
300 }
301 } // namespace AbilityRuntime
302 } // namespace OHOS