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