• 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 
16 #include "js_application.h"
17 
18 #include "context_impl.h"
19 #include "hilog_tag_wrapper.h"
20 #include "js_context_utils.h"
21 #include "js_error_utils.h"
22 #include "js_runtime.h"
23 #include "napi_base_context.h"
24 
25 namespace OHOS {
26 namespace AbilityRuntime {
27 namespace {
28 constexpr size_t ARGC_ZERO = 0;
29 constexpr size_t ARGC_ONE = 1;
30 constexpr size_t ARGC_TWO = 2;
31 constexpr size_t ARGC_THREE = 3;
32 constexpr const char *PERMISSION_GET_BUNDLE_INFO = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED";
33 } // namespace
34 
Finalizer(napi_env env,void * data,void * hint)35 void JsApplication::Finalizer(napi_env env, void *data, void *hint)
36 {
37     TAG_LOGD(AAFwkTag::ABILITY_SIM, "Called.");
38     std::unique_ptr<JsApplication>(static_cast<JsApplication *>(data));
39 }
40 
GetApplicationContext(napi_env env,napi_callback_info info)41 napi_value JsApplication::GetApplicationContext(napi_env env, napi_callback_info info)
42 {
43     return nullptr;
44 }
45 
CreateBundleContext(napi_env env,napi_callback_info info)46 napi_value JsApplication::CreateBundleContext(napi_env env, napi_callback_info info)
47 {
48     return nullptr;
49 }
50 
CreateModuleContext(napi_env env,napi_callback_info info)51 napi_value JsApplication::CreateModuleContext(napi_env env, napi_callback_info info)
52 {
53     GET_NAPI_INFO_AND_CALL(env, info, JsApplication, OnCreateModuleContext);
54 }
55 
OnCreateModuleContext(napi_env env,NapiCallbackInfo & info)56 napi_value JsApplication::OnCreateModuleContext(napi_env env, NapiCallbackInfo &info)
57 {
58     TAG_LOGD(AAFwkTag::ABILITY_SIM, "Called");
59     if (info.argc < ARGC_TWO) {
60         TAG_LOGE(AAFwkTag::ABILITY_SIM, "invalid argc");
61         ThrowTooFewParametersError(env);
62         return CreateJsUndefined(env);
63     }
64 
65     bool stageMode = false;
66     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, info.argv[ARGC_ZERO], stageMode);
67     if (status != napi_ok || !stageMode) {
68         TAG_LOGE(AAFwkTag::ABILITY_SIM, "not stageMode");
69         ThrowInvalidParamError(env, "Parse param context failed, must be a context of stageMode.");
70         return CreateJsUndefined(env);
71     }
72 
73     auto context = OHOS::AbilityRuntime::GetStageModeContext(env, info.argv[ARGC_ZERO]);
74     if (context == nullptr) {
75         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null context");
76         ThrowInvalidParamError(env, "Parse param context failed, must not be nullptr.");
77         return CreateJsUndefined(env);
78     }
79 
80     auto inputContextPtr = Context::ConvertTo<Context>(context);
81     if (inputContextPtr == nullptr) {
82         TAG_LOGE(AAFwkTag::ABILITY_SIM, "Convert to context failed");
83         ThrowInvalidParamError(env, "Parse param context failed, must be a context.");
84         return CreateJsUndefined(env);
85     }
86 
87     std::shared_ptr<std::shared_ptr<Context>> moduleContext = std::make_shared<std::shared_ptr<Context>>();
88     std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
89     if (contextImpl == nullptr) {
90         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null contextImpl");
91         ThrowInvalidParamError(env, "create context failed.");
92         return CreateJsUndefined(env);
93     }
94     std::string moduleName = "";
95     std::string bundleName = "";
96     if (info.argc == ARGC_TWO) {
97         TAG_LOGD(AAFwkTag::ABILITY_SIM, "Called");
98         if (!ConvertFromJsValue(env, info.argv[ARGC_ONE], moduleName)) {
99             TAG_LOGE(AAFwkTag::ABILITY_SIM, "Parse failed");
100             ThrowInvalidParamError(env, "Parse param moduleName failed, moduleName must be string.");
101             return CreateJsUndefined(env);
102         }
103     } else {
104         TAG_LOGD(AAFwkTag::ABILITY_SIM, "Called");
105         if (!CheckCallerIsSystemApp()) {
106             TAG_LOGE(AAFwkTag::ABILITY_SIM, "no system app");
107             ThrowNotSystemAppError(env);
108             return CreateJsUndefined(env);
109         }
110 
111         if (!CheckCallerPermission(PERMISSION_GET_BUNDLE_INFO)) {
112             TAG_LOGE(AAFwkTag::ABILITY_SIM, "no permission");
113             ThrowNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO);
114             return CreateJsUndefined(env);
115         }
116 
117         if (!ConvertFromJsValue(env, info.argv[ARGC_TWO], moduleName)
118             || !ConvertFromJsValue(env, info.argv[ARGC_ONE], bundleName)) {
119             TAG_LOGE(AAFwkTag::ABILITY_SIM, "Parse failed");
120             ThrowInvalidParamError(env, "Parse param failed, moduleName and bundleName must be string.");
121             return CreateJsUndefined(env);
122         }
123     }
124     TAG_LOGD(AAFwkTag::ABILITY_SIM, "moduleName: %{public}s, bundlename: %{public}s",
125         moduleName.c_str(), bundleName.c_str());
126     NapiAsyncTask::ExecuteCallback execute = [moduleName, bundleName, contextImpl,
127         moduleContext, inputContextPtr]() {
128         if (bundleName.empty()) {
129             *moduleContext = contextImpl->CreateModuleContext(moduleName, inputContextPtr);
130         } else {
131             *moduleContext = contextImpl->CreateModuleContext(bundleName, moduleName, inputContextPtr);
132         }
133     };
134 
135     NapiAsyncTask::CompleteCallback complete;
136     SetCreateCompleteCallback(moduleContext, complete);
137 
138     napi_value result = nullptr;
139     NapiAsyncTask::ScheduleHighQos("JsApplication::OnCreateModuleContext",
140         env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
141 
142     return result;
143 }
144 
CreatePluginModuleContext(napi_env env,napi_callback_info info)145 napi_value JsApplication::CreatePluginModuleContext(napi_env env, napi_callback_info info)
146 {
147     return nullptr;
148 }
149 
150 
CheckCallerIsSystemApp()151 bool JsApplication::CheckCallerIsSystemApp()
152 {
153     return true;
154 }
155 
CheckCallerPermission(const std::string & permission)156 bool JsApplication::CheckCallerPermission(const std::string &permission)
157 {
158     return true;
159 }
160 
SetCreateCompleteCallback(std::shared_ptr<std::shared_ptr<Context>> contextPtr,NapiAsyncTask::CompleteCallback & complete)161 void JsApplication::SetCreateCompleteCallback(std::shared_ptr<std::shared_ptr<Context>> contextPtr,
162     NapiAsyncTask::CompleteCallback &complete)
163 {
164     complete = [contextPtr](napi_env env, NapiAsyncTask &task, int32_t status) {
165         auto context = *contextPtr;
166         if (context == nullptr) {
167             TAG_LOGE(AAFwkTag::ABILITY_SIM, "failed to create context");
168             task.Reject(env, CreateJsError(env,
169                 static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), "invalid param."));
170             return;
171         }
172         napi_value value = CreateJsBaseContext(env, context, true);
173         auto systemModule = JsRuntime::LoadSystemModuleByEngine(env, "application.Context", &value, 1);
174         if (systemModule == nullptr) {
175             TAG_LOGW(AAFwkTag::ABILITY_SIM, "invalid systemModule");
176             task.Reject(env, CreateJsError(env,
177                 static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), "invalid param."));
178             return;
179         }
180 
181         napi_value object = systemModule->GetNapiValue();
182         if (!CheckTypeForNapiValue(env, object, napi_object)) {
183             TAG_LOGE(AAFwkTag::ABILITY_SIM, "Failed to get object");
184             task.Reject(env, CreateJsError(env,
185                 static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), "invalid param."));
186             return;
187         }
188 
189         auto workContext = new (std::nothrow) std::weak_ptr<Context>(context);
190         napi_coerce_to_native_binding_object(env, object, DetachCallbackFunc, AttachBaseContext, workContext, nullptr);
191         napi_status ret = napi_wrap(env, object, workContext,
192             [](napi_env, void *data, void *) {
193                 TAG_LOGD(AAFwkTag::ABILITY_SIM, "Finalizer for weak_ptr module context is called");
194                 delete static_cast<std::weak_ptr<Context> *>(data);
195             },
196             nullptr, nullptr);
197         if (ret != napi_ok && workContext != nullptr) {
198             TAG_LOGE(AAFwkTag::ABILITY_SIM, "napi_wrap Failed: %{public}d", ret);
199             delete workContext;
200             return;
201         }
202         task.ResolveWithNoError(env, object);
203     };
204 }
205 
OnCreateBundleContext(napi_env env,NapiCallbackInfo & info)206 napi_value JsApplication::OnCreateBundleContext(napi_env env, NapiCallbackInfo &info)
207 {
208     return nullptr;
209 }
210 
OnCreatePluginModuleContext(napi_env env,NapiCallbackInfo & info)211 napi_value JsApplication::OnCreatePluginModuleContext(napi_env env, NapiCallbackInfo &info)
212 {
213     return nullptr;
214 }
215 
CreateJsContext(napi_env env,const std::shared_ptr<Context> & context)216 napi_value JsApplication::CreateJsContext(napi_env env, const std::shared_ptr<Context> &context)
217 {
218     return nullptr;
219 }
220 
OnGetApplicationContext(napi_env env,NapiCallbackInfo & info)221 napi_value JsApplication::OnGetApplicationContext(napi_env env, NapiCallbackInfo &info)
222 {
223     return nullptr;
224 }
225 
ApplicationInit(napi_env env,napi_value exportObj)226 napi_value ApplicationInit(napi_env env, napi_value exportObj)
227 {
228     TAG_LOGD(AAFwkTag::ABILITY_SIM, "Called");
229     if (env == nullptr || exportObj == nullptr) {
230         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null env or exportObj");
231         return nullptr;
232     }
233 
234     auto jsApplication = std::make_unique<JsApplication>();
235     napi_wrap(env, exportObj, jsApplication.release(), JsApplication::Finalizer, nullptr, nullptr);
236 
237     const char *moduleName = "application";
238     BindNativeFunction(env, exportObj, "getApplicationContext", moduleName,
239         JsApplication::GetApplicationContext);
240 
241     BindNativeFunction(env, exportObj, "createModuleContext", moduleName,
242         JsApplication::CreateModuleContext);
243 
244     BindNativeFunction(env, exportObj, "createBundleContext", moduleName,
245         JsApplication::CreateBundleContext);
246 
247     BindNativeFunction(env, exportObj, "createPluginModuleContext", moduleName,
248         JsApplication::CreatePluginModuleContext);
249     return CreateJsUndefined(env);
250 }
251 } // namespace AbilityRuntime
252 } // namespace OHOS