1 /*
2  * Copyright (c) 2023-2024 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_ability_context.h"
17 
18 #include "ability_business_error.h"
19 #include "hilog_tag_wrapper.h"
20 #include "js_context_utils.h"
21 #include "js_data_converter.h"
22 #include "js_resource_manager_utils.h"
23 #include "js_runtime_utils.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 }
Finalizer(napi_env env,void * data,void * hint)31 void JsAbilityContext::Finalizer(napi_env env, void *data, void *hint)
32 {
33     TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
34     std::unique_ptr<JsAbilityContext>(static_cast<JsAbilityContext*>(data));
35 }
36 
StartAbility(napi_env env,napi_callback_info info)37 napi_value JsAbilityContext::StartAbility(napi_env env, napi_callback_info info)
38 {
39     return nullptr;
40 }
41 
StartAbilityAsCaller(napi_env env,napi_callback_info info)42 napi_value JsAbilityContext::StartAbilityAsCaller(napi_env env, napi_callback_info info)
43 {
44     return nullptr;
45 }
46 
StartRecentAbility(napi_env env,napi_callback_info info)47 napi_value JsAbilityContext::StartRecentAbility(napi_env env, napi_callback_info info)
48 {
49     return nullptr;
50 }
51 
StartAbilityWithAccount(napi_env env,napi_callback_info info)52 napi_value JsAbilityContext::StartAbilityWithAccount(napi_env env, napi_callback_info info)
53 {
54     return nullptr;
55 }
56 
StartAbilityByCall(napi_env env,napi_callback_info info)57 napi_value JsAbilityContext::StartAbilityByCall(napi_env env, napi_callback_info info)
58 {
59     return nullptr;
60 }
61 
StartAbilityForResult(napi_env env,napi_callback_info info)62 napi_value JsAbilityContext::StartAbilityForResult(napi_env env, napi_callback_info info)
63 {
64     return nullptr;
65 }
66 
StartAbilityForResultWithAccount(napi_env env,napi_callback_info info)67 napi_value JsAbilityContext::StartAbilityForResultWithAccount(napi_env env, napi_callback_info info)
68 {
69     return nullptr;
70 }
71 
StartServiceExtensionAbility(napi_env env,napi_callback_info info)72 napi_value JsAbilityContext::StartServiceExtensionAbility(napi_env env, napi_callback_info info)
73 {
74     return nullptr;
75 }
76 
StartServiceExtensionAbilityWithAccount(napi_env env,napi_callback_info info)77 napi_value JsAbilityContext::StartServiceExtensionAbilityWithAccount(napi_env env, napi_callback_info info)
78 {
79     return nullptr;
80 }
81 
StopServiceExtensionAbility(napi_env env,napi_callback_info info)82 napi_value JsAbilityContext::StopServiceExtensionAbility(napi_env env, napi_callback_info info)
83 {
84     return nullptr;
85 }
86 
StopServiceExtensionAbilityWithAccount(napi_env env,napi_callback_info info)87 napi_value JsAbilityContext::StopServiceExtensionAbilityWithAccount(napi_env env, napi_callback_info info)
88 {
89     return nullptr;
90 }
91 
ConnectAbility(napi_env env,napi_callback_info info)92 napi_value JsAbilityContext::ConnectAbility(napi_env env, napi_callback_info info)
93 {
94     return nullptr;
95 }
96 
ConnectAbilityWithAccount(napi_env env,napi_callback_info info)97 napi_value JsAbilityContext::ConnectAbilityWithAccount(napi_env env, napi_callback_info info)
98 {
99     return nullptr;
100 }
101 
DisconnectAbility(napi_env env,napi_callback_info info)102 napi_value JsAbilityContext::DisconnectAbility(napi_env env, napi_callback_info info)
103 {
104     return nullptr;
105 }
106 
TerminateSelf(napi_env env,napi_callback_info info)107 napi_value JsAbilityContext::TerminateSelf(napi_env env, napi_callback_info info)
108 {
109     GET_NAPI_INFO_AND_CALL(env, info, JsAbilityContext, OnTerminateSelf);
110 }
111 
OnTerminateSelf(napi_env env,NapiCallbackInfo & info)112 napi_value JsAbilityContext::OnTerminateSelf(napi_env env, NapiCallbackInfo &info)
113 {
114     TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
115     auto abilityContext = context_.lock();
116     if (abilityContext == nullptr) {
117         return nullptr;
118     }
119     abilityContext->SetTerminating(true);
120 
121     napi_value lastParam = (info.argc > ARGC_ZERO) ? info.argv[ARGC_ZERO] : nullptr;
122     napi_value result = nullptr;
123     auto task = CreateAsyncTaskWithLastParam(env, lastParam, nullptr, nullptr, &result);
124     if (task == nullptr) {
125         return nullptr;
126     }
127 
128     auto errcode = abilityContext->TerminateSelf();
129     if (errcode == 0) {
130         task->Resolve(env, CreateJsUndefined(env));
131     } else {
132         task->Reject(env, CreateJsErrorByNativeErr(env, errcode));
133     }
134 
135     return result;
136 }
137 
TerminateSelfWithResult(napi_env env,napi_callback_info info)138 napi_value JsAbilityContext::TerminateSelfWithResult(napi_env env, napi_callback_info info)
139 {
140     GET_NAPI_INFO_AND_CALL(env, info, JsAbilityContext, OnTerminateSelfWithResult);
141 }
142 
OnTerminateSelfWithResult(napi_env env,NapiCallbackInfo & info)143 napi_value JsAbilityContext::OnTerminateSelfWithResult(napi_env env, NapiCallbackInfo &info)
144 {
145     TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
146     auto abilityContext = context_.lock();
147     if (abilityContext == nullptr) {
148         return nullptr;
149     }
150     abilityContext->SetTerminating(true);
151 
152     napi_value lastParam = (info.argc > ARGC_ONE) ? info.argv[ARGC_ONE] : nullptr;
153     napi_value result = nullptr;
154     auto task = CreateAsyncTaskWithLastParam(env, lastParam, nullptr, nullptr, &result);
155     if (task == nullptr) {
156         return nullptr;
157     }
158 
159     auto errcode = abilityContext->TerminateSelf();
160     if (errcode == 0) {
161         task->Resolve(env, CreateJsUndefined(env));
162     } else {
163         task->Reject(env, CreateJsErrorByNativeErr(env, errcode));
164     }
165 
166     return result;
167 }
168 
RestoreWindowStage(napi_env env,napi_callback_info info)169 napi_value JsAbilityContext::RestoreWindowStage(napi_env env, napi_callback_info info)
170 {
171     return nullptr;
172 }
173 
RequestDialogService(napi_env env,napi_callback_info info)174 napi_value JsAbilityContext::RequestDialogService(napi_env env, napi_callback_info info)
175 {
176     return nullptr;
177 }
178 
IsTerminating(napi_env env,napi_callback_info info)179 napi_value JsAbilityContext::IsTerminating(napi_env env, napi_callback_info info)
180 {
181     GET_NAPI_INFO_AND_CALL(env, info, JsAbilityContext, OnIsTerminating);
182 }
183 
OnIsTerminating(napi_env env,NapiCallbackInfo & info)184 napi_value JsAbilityContext::OnIsTerminating(napi_env env, NapiCallbackInfo &info)
185 {
186     TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
187     auto context = context_.lock();
188     if (context == nullptr) {
189         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null context");
190         return CreateJsUndefined(env);
191     }
192     return CreateJsValue(env, context->IsTerminating());
193 }
194 
CreateJsErrorByNativeErr(napi_env env,int32_t err,const std::string & permission)195 napi_value CreateJsErrorByNativeErr(napi_env env, int32_t err, const std::string &permission)
196 {
197     auto errCode = GetJsErrorCodeByNativeError(err);
198     auto errMsg = (errCode == AbilityErrorCode::ERROR_CODE_PERMISSION_DENIED && !permission.empty()) ?
199         GetNoPermissionErrorMsg(permission) : GetErrorMsg(errCode);
200     return CreateJsError(env, static_cast<int32_t>(errCode), errMsg);
201 }
202 
ConfigurationUpdated(napi_env env,std::shared_ptr<NativeReference> & jsContext,const std::shared_ptr<AppExecFwk::Configuration> & config)203 void JsAbilityContext::ConfigurationUpdated(napi_env env, std::shared_ptr<NativeReference> &jsContext,
204     const std::shared_ptr<AppExecFwk::Configuration> &config)
205 {
206     TAG_LOGD(AAFwkTag::ABILITY_SIM, "called");
207     if (jsContext == nullptr || config == nullptr) {
208         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null jsContext");
209         return;
210     }
211 
212     napi_value value = jsContext->GetNapiValue();
213     if (value == nullptr) {
214         TAG_LOGE(AAFwkTag::ABILITY_SIM, "null value");
215         return;
216     }
217 
218     napi_value method = nullptr;
219     napi_get_named_property(env, value, "onUpdateConfiguration", &method);
220     if (method == nullptr) {
221         TAG_LOGE(AAFwkTag::ABILITY_SIM, "failed");
222         return;
223     }
224 
225     napi_value argv[] = { CreateJsConfiguration(env, *config) };
226     napi_value callResult = nullptr;
227     napi_call_function(env, nullptr, method, 1, argv, &callResult);
228 }
229 
CreateJsAbilityContext(napi_env env,const std::shared_ptr<AbilityContext> & context)230 napi_value CreateJsAbilityContext(napi_env env, const std::shared_ptr<AbilityContext> &context)
231 {
232     napi_value object = CreateJsBaseContext(env, context);
233 
234     std::unique_ptr<JsAbilityContext> jsContext = std::make_unique<JsAbilityContext>(context);
235     napi_wrap(env, object, jsContext.release(), JsAbilityContext::Finalizer, nullptr, nullptr);
236 
237     auto resourceManager = context->GetResourceManager();
238     if (resourceManager != nullptr) {
239         napi_set_named_property(env, object, "resourceManager",
240             CreateJsResourceManager(env, resourceManager, context));
241     }
242 
243     auto abilityInfo = context->GetAbilityInfo();
244     if (abilityInfo != nullptr) {
245         napi_set_named_property(
246             env, object, "abilityInfo", CreateJsAbilityInfo(env, *abilityInfo));
247     }
248 
249     auto configuration = context->GetConfiguration();
250     if (configuration != nullptr) {
251         napi_set_named_property(
252             env, object, "config", CreateJsConfiguration(env, *configuration));
253     }
254 
255     const char *moduleName = "JsAbilityContext";
256     BindNativeFunction(env, object, "startAbility", moduleName, JsAbilityContext::StartAbility);
257     BindNativeFunction(env, object, "startAbilityAsCaller", moduleName, JsAbilityContext::StartAbilityAsCaller);
258     BindNativeFunction(env, object, "startAbilityWithAccount", moduleName,
259         JsAbilityContext::StartAbilityWithAccount);
260     BindNativeFunction(env, object, "startAbilityByCall", moduleName, JsAbilityContext::StartAbilityByCall);
261     BindNativeFunction(env, object, "startAbilityForResult", moduleName, JsAbilityContext::StartAbilityForResult);
262     BindNativeFunction(env, object, "startAbilityForResultWithAccount", moduleName,
263         JsAbilityContext::StartAbilityForResultWithAccount);
264     BindNativeFunction(env, object, "startServiceExtensionAbility", moduleName,
265         JsAbilityContext::StartServiceExtensionAbility);
266     BindNativeFunction(env, object, "startServiceExtensionAbilityWithAccount", moduleName,
267         JsAbilityContext::StartServiceExtensionAbilityWithAccount);
268     BindNativeFunction(env, object, "stopServiceExtensionAbility", moduleName,
269         JsAbilityContext::StopServiceExtensionAbility);
270     BindNativeFunction(env, object, "stopServiceExtensionAbilityWithAccount", moduleName,
271         JsAbilityContext::StopServiceExtensionAbilityWithAccount);
272     BindNativeFunction(env, object, "connectAbility", moduleName, JsAbilityContext::ConnectAbility);
273     BindNativeFunction(env, object, "connectServiceExtensionAbility", moduleName, JsAbilityContext::ConnectAbility);
274     BindNativeFunction(env, object, "connectAbilityWithAccount", moduleName,
275         JsAbilityContext::ConnectAbilityWithAccount);
276     BindNativeFunction(env, object, "connectServiceExtensionAbilityWithAccount", moduleName,
277         JsAbilityContext::ConnectAbilityWithAccount);
278     BindNativeFunction(env, object, "disconnectAbility", moduleName, JsAbilityContext::DisconnectAbility);
279     BindNativeFunction(
280         env, object, "disconnectServiceExtensionAbility", moduleName, JsAbilityContext::DisconnectAbility);
281     BindNativeFunction(env, object, "terminateSelf", moduleName, JsAbilityContext::TerminateSelf);
282     BindNativeFunction(env, object, "terminateSelfWithResult", moduleName,
283         JsAbilityContext::TerminateSelfWithResult);
284     BindNativeFunction(env, object, "restoreWindowStage", moduleName, JsAbilityContext::RestoreWindowStage);
285     BindNativeFunction(env, object, "isTerminating", moduleName, JsAbilityContext::IsTerminating);
286     BindNativeFunction(env, object, "startRecentAbility", moduleName,
287         JsAbilityContext::StartRecentAbility);
288     BindNativeFunction(env, object, "requestDialogService", moduleName,
289         JsAbilityContext::RequestDialogService);
290 
291     return object;
292 }
293 } // namespace AbilityRuntime
294 } // namespace OHOS
295