• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_application.h"
17 
18 #include "ability_runtime_error_util.h"
19 #include "accesstoken_kit.h"
20 #include "app_mgr_client.h"
21 #include "context_impl.h"
22 #include "hilog_tag_wrapper.h"
23 #include "js_application_context_utils.h"
24 #include "js_error_utils.h"
25 #include "js_runtime_utils.h"
26 #include "js_context_utils.h"
27 #include "napi_base_context.h"
28 #include "singleton.h"
29 
30 namespace OHOS {
31 namespace AbilityRuntime {
32 namespace {
33     constexpr size_t ARGC_ZERO = 0;
34     constexpr size_t ARGC_ONE = 1;
35     constexpr size_t ARGC_TWO = 2;
36     constexpr size_t ARGC_THREE = 3;
37     constexpr size_t ARGC_FOUR = 4;
38     constexpr const char* PERMISSION_GET_BUNDLE_INFO = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED";
39 }
Finalizer(napi_env env,void * data,void * hint)40 void JsApplication::Finalizer(napi_env env, void *data, void *hint)
41 {
42     TAG_LOGD(AAFwkTag::APPKIT, "Called.");
43     std::unique_ptr<JsApplication>(static_cast<JsApplication *>(data));
44 }
45 
GetApplicationContext(napi_env env,napi_callback_info info)46 napi_value JsApplication::GetApplicationContext(napi_env env, napi_callback_info info)
47 {
48     GET_NAPI_INFO_AND_CALL(env, info, JsApplication, OnGetApplicationContext);
49 }
50 
OnGetApplicationContext(napi_env env,NapiCallbackInfo & info)51 napi_value JsApplication::OnGetApplicationContext(napi_env env, NapiCallbackInfo &info)
52 {
53     TAG_LOGD(AAFwkTag::APPKIT, "Called.");
54     napi_value value = JsApplicationContextUtils::CreateJsApplicationContext(env);
55     auto systemModule = JsRuntime::LoadSystemModuleByEngine(env, "application.ApplicationContext", &value, 1);
56     if (systemModule == nullptr) {
57         TAG_LOGE(AAFwkTag::APPKIT, "invalid systemModule");
58         AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INTERNAL_ERROR);
59         return CreateJsUndefined(env);
60     }
61     napi_value object = systemModule->GetNapiValue();
62     if (!CheckTypeForNapiValue(env, object, napi_object)) {
63         TAG_LOGE(AAFwkTag::APPKIT, "failed to get context native object");
64         AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INTERNAL_ERROR);
65         return CreateJsUndefined(env);
66     }
67 
68     auto applicationContext = ApplicationContext::GetInstance();
69     auto workContext = new (std::nothrow) std::weak_ptr<ApplicationContext>(applicationContext);
70     napi_coerce_to_native_binding_object(
71         env, object, DetachCallbackFunc, AttachApplicationContext, workContext, nullptr);
72     if (workContext != nullptr) {
73         auto res = napi_wrap(env, object, workContext,
74             [](napi_env, void *data, void *) {
75               TAG_LOGD(AAFwkTag::APPKIT, "Finalizer for weak_ptr application context is called");
76               delete static_cast<std::weak_ptr<ApplicationContext> *>(data);
77               data = nullptr;
78             },
79             nullptr, nullptr);
80         if (res != napi_ok && workContext != nullptr) {
81             TAG_LOGE(AAFwkTag::APPKIT, "napi_wrap failed:%{public}d", res);
82             delete workContext;
83             return CreateJsUndefined(env);
84         }
85     }
86     return object;
87 }
88 
CreateModuleContext(napi_env env,napi_callback_info info)89 napi_value JsApplication::CreateModuleContext(napi_env env, napi_callback_info info)
90 {
91     GET_NAPI_INFO_AND_CALL(env, info, JsApplication, OnCreateModuleContext);
92 }
93 
CreateBundleContext(napi_env env,napi_callback_info info)94 napi_value JsApplication::CreateBundleContext(napi_env env, napi_callback_info info)
95 {
96     GET_NAPI_INFO_AND_CALL(env, info, JsApplication, OnCreateBundleContext);
97 }
98 
CreatePluginModuleContext(napi_env env,napi_callback_info info)99 napi_value JsApplication::CreatePluginModuleContext(napi_env env, napi_callback_info info)
100 {
101     GET_NAPI_INFO_AND_CALL(env, info, JsApplication, OnCreatePluginModuleContext);
102 }
103 
CreatePluginModuleContextForBundle(napi_env env,napi_callback_info info)104 napi_value JsApplication::CreatePluginModuleContextForBundle(napi_env env, napi_callback_info info)
105 {
106     GET_NAPI_INFO_AND_CALL(env, info, JsApplication, OnCreatePluginModuleContextForBundle);
107 }
108 
OnCreatePluginModuleContext(napi_env env,NapiCallbackInfo & info)109 napi_value JsApplication::OnCreatePluginModuleContext(napi_env env, NapiCallbackInfo &info)
110 {
111     if (info.argc < ARGC_THREE) {
112         ThrowTooFewParametersError(env);
113         return CreateJsUndefined(env);
114     }
115 
116     bool stageMode = false;
117     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, info.argv[ARGC_ZERO], stageMode);
118     if (status != napi_ok || !stageMode) {
119         ThrowInvalidParamError(env, "Parse param context failed, must be a context of stageMode.");
120         return CreateJsUndefined(env);
121     }
122 
123     auto context = OHOS::AbilityRuntime::GetStageModeContext(env, info.argv[ARGC_ZERO]);
124     if (context == nullptr) {
125         ThrowInvalidParamError(env, "Parse param context failed, must not be nullptr.");
126         return CreateJsUndefined(env);
127     }
128 
129     auto inputContextPtr = Context::ConvertTo<Context>(context);
130     if (inputContextPtr == nullptr) {
131         ThrowInvalidParamError(env, "Parse param context failed, must be a context.");
132         return CreateJsUndefined(env);
133     }
134 
135     std::shared_ptr<std::shared_ptr<Context>> moduleContext = std::make_shared<std::shared_ptr<Context>>();
136     std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
137     if (contextImpl == nullptr) {
138         ThrowInvalidParamError(env, "create context failed.");
139         return CreateJsUndefined(env);
140     }
141     contextImpl->SetProcessName(context->GetProcessName());
142     std::string moduleName = "";
143     std::string pluginBundleName = "";
144 
145     if (!ConvertFromJsValue(env, info.argv[ARGC_TWO], moduleName)
146         || !ConvertFromJsValue(env, info.argv[ARGC_ONE], pluginBundleName)) {
147         ThrowInvalidParamError(env, "Parse param failed, moduleName and pluginBundleName must be string.");
148         return CreateJsUndefined(env);
149     }
150 
151     TAG_LOGD(AAFwkTag::APPKIT, "moduleName: %{public}s, pluginBundleName: %{public}s",
152         moduleName.c_str(), pluginBundleName.c_str());
153     NapiAsyncTask::ExecuteCallback execute = [moduleName, pluginBundleName, contextImpl,
154         moduleContext, inputContextPtr]() {
155         if (contextImpl != nullptr) {
156             *moduleContext = contextImpl->CreatePluginContext(pluginBundleName, moduleName, inputContextPtr);
157         }
158     };
159 
160     NapiAsyncTask::CompleteCallback complete;
161     SetCreateCompleteCallback(moduleContext, complete);
162 
163     napi_value result = nullptr;
164     NapiAsyncTask::ScheduleHighQos("JsApplication::OnCreatePluginModuleContext",
165         env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
166 
167     return result;
168 }
169 
OnCreatePluginModuleContextForBundle(napi_env env,NapiCallbackInfo & info)170 napi_value JsApplication::OnCreatePluginModuleContextForBundle(napi_env env, NapiCallbackInfo &info)
171 {
172     std::string moduleName = "";
173     std::string pluginBundleName = "";
174     std::string hostBundleName = "";
175     if (!VerifyCreatePluginContextParams(env, info, moduleName, pluginBundleName, hostBundleName)) {
176         TAG_LOGE(AAFwkTag::APPKIT, "invalid params");
177         return CreateJsUndefined(env);
178     }
179 
180     bool stageMode = false;
181     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, info.argv[ARGC_ZERO], stageMode);
182     if (status != napi_ok || !stageMode) {
183         ThrowInvalidParamError(env, "Parse param context failed, must be a context of stageMode.");
184         return CreateJsUndefined(env);
185     }
186 
187     auto context = OHOS::AbilityRuntime::GetStageModeContext(env, info.argv[ARGC_ZERO]);
188     if (context == nullptr) {
189         ThrowInvalidParamError(env, "Parse param context failed, must not be nullptr.");
190         return CreateJsUndefined(env);
191     }
192     auto inputContextPtr = Context::ConvertTo<Context>(context);
193     if (inputContextPtr == nullptr) {
194         ThrowInvalidParamError(env, "Parse param context failed, must be a context.");
195         return CreateJsUndefined(env);
196     }
197 
198     std::shared_ptr<std::shared_ptr<Context>> moduleContext = std::make_shared<std::shared_ptr<Context>>();
199     std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
200     if (contextImpl == nullptr) {
201         ThrowInvalidParamError(env, "create context failed.");
202         return CreateJsUndefined(env);
203     }
204     contextImpl->SetProcessName(context->GetProcessName());
205 
206     TAG_LOGD(AAFwkTag::APPKIT, "moduleName: %{public}s, pluginBundleName: %{public}s, bundleName: %{public}s",
207         moduleName.c_str(), pluginBundleName.c_str(), hostBundleName.c_str());
208     NapiAsyncTask::ExecuteCallback execute = [moduleName, pluginBundleName, hostBundleName, contextImpl,
209         moduleContext, inputContextPtr]() {
210         if (contextImpl != nullptr) {
211              *moduleContext = contextImpl->CreateTargetPluginContext(
212                  hostBundleName, pluginBundleName, moduleName, inputContextPtr);
213         }
214     };
215 
216     NapiAsyncTask::CompleteCallback complete;
217     SetCreateCompleteCallback(moduleContext, complete);
218 
219     napi_value result = nullptr;
220     NapiAsyncTask::ScheduleHighQos("JsApplication::OnCreatePluginModuleContext",
221         env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
222 
223     return result;
224 }
225 
VerifyCreatePluginContextParams(napi_env env,NapiCallbackInfo & info,std::string & moduleName,std::string & pluginBundleName,std::string & hostBundleName)226 bool JsApplication::VerifyCreatePluginContextParams(napi_env env, NapiCallbackInfo &info, std::string &moduleName,
227     std::string &pluginBundleName, std::string &hostBundleName)
228 {
229     if (info.argc != ARGC_FOUR) {
230         TAG_LOGE(AAFwkTag::APPKIT, "wrong number of params");
231         ThrowTooFewParametersError(env);
232         return false;
233     }
234     if (!ConvertFromJsValue(env, info.argv[ARGC_TWO], moduleName)
235         || !ConvertFromJsValue(env, info.argv[ARGC_ONE], pluginBundleName)
236         || !ConvertFromJsValue(env, info.argv[ARGC_THREE], hostBundleName)) {
237         ThrowInvalidParamError(env, "Parse param failed, moduleName and pluginBundleName must be string.");
238         return false;
239     }
240     if (!CheckCallerIsSystemApp()) {
241         TAG_LOGE(AAFwkTag::APPKIT, "no system app");
242         ThrowNotSystemAppError(env);
243         return false;
244     }
245     if (!CheckCallerPermission(PERMISSION_GET_BUNDLE_INFO)) {
246         TAG_LOGE(AAFwkTag::APPKIT, "no permission");
247         ThrowNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO);
248         return false;
249     }
250     return true;
251 }
252 
OnCreateModuleContext(napi_env env,NapiCallbackInfo & info)253 napi_value JsApplication::OnCreateModuleContext(napi_env env, NapiCallbackInfo &info)
254 {
255     TAG_LOGD(AAFwkTag::APPKIT, "Called");
256     if (info.argc < ARGC_TWO) {
257         TAG_LOGE(AAFwkTag::APPKIT, "invalid argc");
258         ThrowTooFewParametersError(env);
259         return CreateJsUndefined(env);
260     }
261 
262     bool stageMode = false;
263     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, info.argv[ARGC_ZERO], stageMode);
264     if (status != napi_ok || !stageMode) {
265         TAG_LOGE(AAFwkTag::APPKIT, "not stageMode");
266         ThrowInvalidParamError(env, "Parse param context failed, must be a context of stageMode.");
267         return CreateJsUndefined(env);
268     }
269 
270     auto context = OHOS::AbilityRuntime::GetStageModeContext(env, info.argv[ARGC_ZERO]);
271     if (context == nullptr) {
272         TAG_LOGE(AAFwkTag::APPKIT, "null context");
273         ThrowInvalidParamError(env, "Parse param context failed, must not be nullptr.");
274         return CreateJsUndefined(env);
275     }
276 
277     auto inputContextPtr = Context::ConvertTo<Context>(context);
278     if (inputContextPtr == nullptr) {
279         TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed");
280         ThrowInvalidParamError(env, "Parse param context failed, must be a context.");
281         return CreateJsUndefined(env);
282     }
283 
284     std::shared_ptr<std::shared_ptr<Context>> moduleContext = std::make_shared<std::shared_ptr<Context>>();
285     std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
286     if (contextImpl == nullptr) {
287         TAG_LOGE(AAFwkTag::APPKIT, "null contextImpl");
288         ThrowInvalidParamError(env, "create context failed.");
289         return CreateJsUndefined(env);
290     }
291     contextImpl->SetProcessName(context->GetProcessName());
292     std::string moduleName = "";
293     std::string bundleName = "";
294     if (info.argc == ARGC_TWO) {
295         TAG_LOGD(AAFwkTag::APPKIT, "Called");
296         if (!ConvertFromJsValue(env, info.argv[ARGC_ONE], moduleName)) {
297             TAG_LOGE(AAFwkTag::APPKIT, "Parse failed");
298             ThrowInvalidParamError(env, "Parse param moduleName failed, moduleName must be string.");
299             return CreateJsUndefined(env);
300         }
301     } else {
302         TAG_LOGD(AAFwkTag::APPKIT, "Called");
303         if (!CheckCallerIsSystemApp()) {
304             TAG_LOGE(AAFwkTag::APPKIT, "no system app");
305             ThrowNotSystemAppError(env);
306             return CreateJsUndefined(env);
307         }
308 
309         if (!CheckCallerPermission(PERMISSION_GET_BUNDLE_INFO)) {
310             TAG_LOGE(AAFwkTag::APPKIT, "no permission");
311             ThrowNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO);
312             return CreateJsUndefined(env);
313         }
314 
315         if (!ConvertFromJsValue(env, info.argv[ARGC_TWO], moduleName)
316             || !ConvertFromJsValue(env, info.argv[ARGC_ONE], bundleName)) {
317             TAG_LOGE(AAFwkTag::APPKIT, "Parse failed");
318             ThrowInvalidParamError(env, "Parse param failed, moduleName and bundleName must be string.");
319             return CreateJsUndefined(env);
320         }
321     }
322     TAG_LOGD(AAFwkTag::APPKIT, "moduleName: %{public}s, bundlename: %{public}s",
323         moduleName.c_str(), bundleName.c_str());
324     NapiAsyncTask::ExecuteCallback execute = [moduleName, bundleName, contextImpl,
325         moduleContext, inputContextPtr]() {
326         if (bundleName.empty()) {
327             *moduleContext = contextImpl->CreateModuleContext(moduleName, inputContextPtr);
328         } else {
329             *moduleContext = contextImpl->CreateModuleContext(bundleName, moduleName, inputContextPtr);
330         }
331     };
332 
333     NapiAsyncTask::CompleteCallback complete;
334     SetCreateCompleteCallback(moduleContext, complete);
335 
336     napi_value result = nullptr;
337     NapiAsyncTask::ScheduleHighQos("JsApplication::OnCreateModuleContext",
338         env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
339 
340     return result;
341 }
342 
CheckCallerIsSystemApp()343 bool JsApplication::CheckCallerIsSystemApp()
344 {
345     auto selfToken = IPCSkeleton::GetSelfTokenID();
346     if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) {
347         return false;
348     }
349     return true;
350 }
351 
CheckCallerPermission(const std::string & permission)352 bool JsApplication::CheckCallerPermission(const std::string &permission)
353 {
354     auto selfToken = IPCSkeleton::GetSelfTokenID();
355     int ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(selfToken, permission);
356     if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
357         return false;
358     }
359     return true;
360 }
361 
362 
OnCreateBundleContext(napi_env env,NapiCallbackInfo & info)363 napi_value JsApplication::OnCreateBundleContext(napi_env env, NapiCallbackInfo &info)
364 {
365     TAG_LOGD(AAFwkTag::APPKIT, "Called");
366     if (!CheckCallerIsSystemApp()) {
367         TAG_LOGE(AAFwkTag::APPKIT, "no system app");
368         ThrowNotSystemAppError(env);
369         return CreateJsUndefined(env);
370     }
371 
372     if (info.argc < ARGC_TWO) {
373         TAG_LOGE(AAFwkTag::APPKIT, "invalid argc");
374         ThrowTooFewParametersError(env);
375         return CreateJsUndefined(env);
376     }
377 
378     if (!CheckCallerPermission(PERMISSION_GET_BUNDLE_INFO)) {
379         TAG_LOGE(AAFwkTag::APPKIT, "no permission");
380         ThrowNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO);
381         return CreateJsUndefined(env);
382     }
383 
384     bool stageMode = false;
385     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, info.argv[ARGC_ZERO], stageMode);
386     if (status != napi_ok || !stageMode) {
387         TAG_LOGE(AAFwkTag::APPKIT, "not stageMode");
388         ThrowInvalidParamError(env, "Parse param context failed, must be a context of stageMode.");
389         return CreateJsUndefined(env);
390     }
391 
392     auto context = OHOS::AbilityRuntime::GetStageModeContext(env, info.argv[ARGC_ZERO]);
393     if (context == nullptr) {
394         TAG_LOGE(AAFwkTag::APPKIT, "null context");
395         ThrowInvalidParamError(env, "Parse param context failed, must not be nullptr.");
396         return CreateJsUndefined(env);
397     }
398 
399     auto inputContextPtr = Context::ConvertTo<Context>(context);
400     if (inputContextPtr == nullptr) {
401         TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed");
402         ThrowInvalidParamError(env, "Parse param context failed, must be a context.");
403         return CreateJsUndefined(env);
404     }
405 
406     std::string bundleName;
407     if (!ConvertFromJsValue(env, info.argv[ARGC_ONE], bundleName)) {
408         TAG_LOGE(AAFwkTag::APPKIT, "Parse bundleName failed");
409         ThrowInvalidParamError(env, "Parse param bundleName failed, bundleName must be string.");
410         return CreateJsUndefined(env);
411     }
412 
413     auto bundleContext = std::make_shared<std::shared_ptr<Context>>();
414     std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
415     contextImpl->SetProcessName(context->GetProcessName());
416 
417     NapiAsyncTask::ExecuteCallback execute = [bundleName, contextImpl,
418         bundleContext, inputContextPtr]() {
419         contextImpl->CreateBundleContext(*bundleContext, bundleName, inputContextPtr);
420     };
421 
422     NapiAsyncTask::CompleteCallback complete;
423     SetCreateCompleteCallback(bundleContext, complete);
424 
425     napi_value result = nullptr;
426     NapiAsyncTask::ScheduleHighQos("JsApplication::OnCreateBundleContext",
427         env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
428 
429     return result;
430 }
431 
SetCreateCompleteCallback(std::shared_ptr<std::shared_ptr<Context>> contextPtr,NapiAsyncTask::CompleteCallback & complete)432 void JsApplication::SetCreateCompleteCallback(std::shared_ptr<std::shared_ptr<Context>> contextPtr,
433     NapiAsyncTask::CompleteCallback &complete)
434 {
435     TAG_LOGD(AAFwkTag::APPKIT, "Called");
436     complete = [contextPtr](napi_env env, NapiAsyncTask &task, int32_t status) {
437         auto context = *contextPtr;
438         if (!context) {
439             TAG_LOGE(AAFwkTag::APPKIT, "failed to create context");
440             task.Reject(env, CreateJsError(env,
441                 static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), "invalid param."));
442             return;
443         }
444         napi_value value = CreateJsBaseContext(env, context, true);
445         auto systemModule = JsRuntime::LoadSystemModuleByEngine(env, "application.Context", &value, 1);
446         if (systemModule == nullptr) {
447             TAG_LOGW(AAFwkTag::APPKIT, "invalid systemModule");
448             task.Reject(env, CreateJsError(env,
449                 static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), "invalid param."));
450             return;
451         }
452 
453         napi_value object = systemModule->GetNapiValue();
454         if (!CheckTypeForNapiValue(env, object, napi_object)) {
455             TAG_LOGE(AAFwkTag::APPKIT, "Failed to get object");
456             task.Reject(env, CreateJsError(env,
457                 static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), "invalid param."));
458             return;
459         }
460 
461         auto workContext = new (std::nothrow) std::weak_ptr<Context>(context);
462         napi_coerce_to_native_binding_object(env, object, DetachCallbackFunc, AttachBaseContext, workContext, nullptr);
463         napi_status ret = napi_wrap(env, object, workContext,
464             [](napi_env, void *data, void *) {
465                 TAG_LOGD(AAFwkTag::APPKIT, "Finalizer for weak_ptr module context is called");
466                 delete static_cast<std::weak_ptr<Context> *>(data);
467             },
468             nullptr, nullptr);
469         if (ret != napi_ok && workContext != nullptr) {
470             TAG_LOGE(AAFwkTag::APPKIT, "napi_wrap Failed: %{public}d", ret);
471             delete workContext;
472             return;
473         }
474         task.ResolveWithNoError(env, object);
475     };
476 }
477 
CreateJsContext(napi_env env,const std::shared_ptr<Context> & context)478 napi_value JsApplication::CreateJsContext(napi_env env, const std::shared_ptr<Context> &context)
479 {
480     napi_value value = CreateJsBaseContext(env, context, true);
481     auto systemModule = JsRuntime::LoadSystemModuleByEngine(env, "application.Context", &value, 1);
482     if (systemModule == nullptr) {
483         TAG_LOGW(AAFwkTag::APPKIT, "invalid systemModule");
484         ThrowInvalidParamError(env, "invalid param.");
485         return CreateJsUndefined(env);
486     }
487     napi_value object = systemModule->GetNapiValue();
488     if (!CheckTypeForNapiValue(env, object, napi_object)) {
489         TAG_LOGE(AAFwkTag::APPKIT, "Failed to get object");
490         ThrowInvalidParamError(env, "invalid param.");
491         return CreateJsUndefined(env);
492     }
493 
494     auto workContext = new (std::nothrow) std::weak_ptr<Context>(context);
495     napi_coerce_to_native_binding_object(env, object, DetachCallbackFunc, AttachBaseContext, workContext, nullptr);
496     napi_status status = napi_wrap(env, object, workContext,
497         [](napi_env, void *data, void *) {
498             TAG_LOGD(AAFwkTag::APPKIT, "Finalizer for weak_ptr module context is called");
499             delete static_cast<std::weak_ptr<Context> *>(data);
500         },
501         nullptr, nullptr);
502     if (status != napi_ok && workContext != nullptr) {
503         TAG_LOGE(AAFwkTag::APPKIT, "napi_wrap Failed: %{public}d", status);
504         delete workContext;
505         ThrowInvalidParamError(env, "invalid param.");
506         return CreateJsUndefined(env);
507     }
508 
509     return object;
510 }
511 
PromoteCurrentToCandidateMasterProcess(napi_env env,napi_callback_info info)512 napi_value JsApplication::PromoteCurrentToCandidateMasterProcess(napi_env env, napi_callback_info info)
513 {
514     TAG_LOGD(AAFwkTag::APPKIT, "called");
515     GET_NAPI_INFO_AND_CALL(env, info, JsApplication, OnPromoteCurrentToCandidateMasterProcess);
516 }
517 
OnPromoteCurrentToCandidateMasterProcess(napi_env env,NapiCallbackInfo & info)518 napi_value JsApplication::OnPromoteCurrentToCandidateMasterProcess(napi_env env, NapiCallbackInfo& info)
519 {
520     // only support one params
521     if (info.argc == ARGC_ZERO) {
522         TAG_LOGE(AAFwkTag::APPKIT, "Not enough params");
523         ThrowInvalidParamError(env, "Not enough params");
524         return CreateJsUndefined(env);
525     }
526 
527     bool isInsertToHead = false;
528     if (!ConvertFromJsValue(env, info.argv[ARGC_ZERO], isInsertToHead)) {
529         TAG_LOGE(AAFwkTag::APPKIT, "Parse isInsertToHead failed");
530         ThrowInvalidParamError(env,
531             "Parse param isInsertToHead failed, isInsertToHead must be boolean.");
532         return CreateJsUndefined(env);
533     }
534 
535     auto errCode = std::make_shared<int32_t>(ERR_OK);
536     NapiAsyncTask::ExecuteCallback execute = [isInsertToHead, errCode]() {
537         auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
538         if (appMgrClient == nullptr) {
539             TAG_LOGE(AAFwkTag::APPKIT, "Null appMgrClient");
540             *errCode = static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INNER);
541             return;
542         }
543         *errCode = appMgrClient->PromoteCurrentToCandidateMasterProcess(isInsertToHead);
544     };
545     NapiAsyncTask::CompleteCallback complete = [errCode](napi_env env, NapiAsyncTask& task, int32_t status) {
546         if (*errCode == ERR_OK) {
547             TAG_LOGD(AAFwkTag::APPKIT, "promote to standby master process success");
548             task.ResolveWithNoError(env, CreateJsUndefined(env));
549             return ;
550         }
551         task.Reject(env, CreateJsErrorByNativeErr(env, *errCode));
552     };
553     napi_value result = nullptr;
554     NapiAsyncTask::ScheduleHighQos("JsApplication::OnPromoteCurrentToCandidateMasterProcess",
555         env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
556     return result;
557 }
558 
DemoteCurrentFromCandidateMasterProcess(napi_env env,napi_callback_info info)559 napi_value JsApplication::DemoteCurrentFromCandidateMasterProcess(napi_env env, napi_callback_info info)
560 {
561     TAG_LOGD(AAFwkTag::APPKIT, "called");
562     GET_NAPI_INFO_AND_CALL(env, info, JsApplication, OnDemoteCurrentFromCandidateMasterProcess);
563 }
564 
OnDemoteCurrentFromCandidateMasterProcess(napi_env env,NapiCallbackInfo & info)565 napi_value JsApplication::OnDemoteCurrentFromCandidateMasterProcess(napi_env env, NapiCallbackInfo& info)
566 {
567     auto errCode = std::make_shared<int32_t>(ERR_OK);
568     NapiAsyncTask::ExecuteCallback execute = [errCode]() {
569     auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
570         if (appMgrClient == nullptr) {
571             TAG_LOGE(AAFwkTag::APPKIT, "Null appMgrClient");
572             *errCode = static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INNER);
573             return;
574         }
575         *errCode = appMgrClient->DemoteCurrentFromCandidateMasterProcess();
576     };
577     NapiAsyncTask::CompleteCallback complete = [errCode](napi_env env, NapiAsyncTask& task, int32_t status) {
578         if (*errCode == ERR_OK) {
579             TAG_LOGD(AAFwkTag::APPKIT, "demote to standby master process success");
580             task.ResolveWithNoError(env, CreateJsUndefined(env));
581             return ;
582         }
583         task.Reject(env, CreateJsErrorByNativeErr(env, *errCode));
584     };
585     napi_value result = nullptr;
586     NapiAsyncTask::ScheduleHighQos("JsApplication::OnDemoteCurrentFromCandidateMasterProcess",
587         env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
588     return result;
589 }
590 
ApplicationInit(napi_env env,napi_value exportObj)591 napi_value ApplicationInit(napi_env env, napi_value exportObj)
592 {
593     TAG_LOGD(AAFwkTag::APPKIT, "Called");
594     if (env == nullptr || exportObj == nullptr) {
595         TAG_LOGE(AAFwkTag::APPKIT, "null env or exportObj");
596         return nullptr;
597     }
598 
599     auto jsApplication = std::make_unique<JsApplication>();
600     napi_wrap(env, exportObj, jsApplication.release(), JsApplication::Finalizer, nullptr, nullptr);
601 
602     const char *moduleName = "application";
603     BindNativeFunction(env, exportObj, "getApplicationContext", moduleName,
604         JsApplication::GetApplicationContext);
605 
606     BindNativeFunction(env, exportObj, "createModuleContext", moduleName,
607         JsApplication::CreateModuleContext);
608 
609     BindNativeFunction(env, exportObj, "createBundleContext", moduleName,
610         JsApplication::CreateBundleContext);
611 
612     BindNativeFunction(env, exportObj, "createPluginModuleContext", moduleName,
613         JsApplication::CreatePluginModuleContext);
614 
615     BindNativeFunction(env, exportObj, "promoteCurrentToCandidateMasterProcess", moduleName,
616         JsApplication::PromoteCurrentToCandidateMasterProcess);
617 
618     BindNativeFunction(env, exportObj, "demoteCurrentFromCandidateMasterProcess", moduleName,
619         JsApplication::DemoteCurrentFromCandidateMasterProcess);
620 
621     BindNativeFunction(env, exportObj, "createPluginModuleContextForHostBundle", moduleName,
622         JsApplication::CreatePluginModuleContextForBundle);
623 
624     return CreateJsUndefined(env);
625 }
626 } // namespace AbilityRuntime
627 } // namespace OHOS