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