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_startup_config.h"
17 
18 #include "hilog_tag_wrapper.h"
19 #include "js_runtime_utils.h"
20 
21 namespace OHOS {
22 namespace AbilityRuntime {
23 
JsStartupConfig(napi_env env)24 JsStartupConfig::JsStartupConfig(napi_env env) : StartupConfig(), env_(env)
25 {}
26 
27 JsStartupConfig::~JsStartupConfig() = default;
28 
Init(std::unique_ptr<NativeReference> & configEntryJsRef)29 int32_t JsStartupConfig::Init(std::unique_ptr<NativeReference> &configEntryJsRef)
30 {
31     if (configEntryJsRef == nullptr) {
32         TAG_LOGE(AAFwkTag::STARTUP, "config entry null");
33         return ERR_STARTUP_INTERNAL_ERROR;
34     }
35     HandleScope handleScope(env_);
36 
37     napi_value configEntry = configEntryJsRef->GetNapiValue();
38     if (!CheckTypeForNapiValue(env_, configEntry, napi_object)) {
39         TAG_LOGE(AAFwkTag::STARTUP, "not napi object");
40         return ERR_STARTUP_INTERNAL_ERROR;
41     }
42     napi_value onConfig = nullptr;
43     napi_get_named_property(env_, configEntry, "onConfig", &onConfig);
44     if (onConfig == nullptr) {
45         TAG_LOGE(AAFwkTag::STARTUP, "onConfig invalid");
46         return ERR_STARTUP_INTERNAL_ERROR;
47     }
48     bool isCallable = false;
49     napi_is_callable(env_, onConfig, &isCallable);
50     if (!isCallable) {
51         TAG_LOGE(AAFwkTag::STARTUP, "onConfig not callable");
52         return ERR_STARTUP_INTERNAL_ERROR;
53     }
54     napi_value config = nullptr;
55     napi_call_function(env_, configEntry, onConfig, 0, nullptr, &config);
56     if (config == nullptr) {
57         TAG_LOGE(AAFwkTag::STARTUP, "config null");
58         return ERR_STARTUP_INTERNAL_ERROR;
59     }
60 
61     InitAwaitTimeout(env_, config);
62     InitListener(env_, config);
63     return ERR_OK;
64 }
65 
Init(napi_value config)66 int32_t JsStartupConfig::Init(napi_value config)
67 {
68     if (config == nullptr) {
69         TAG_LOGE(AAFwkTag::STARTUP, "config null");
70         return ERR_STARTUP_INTERNAL_ERROR;
71     }
72 
73     InitAwaitTimeout(env_, config);
74     InitListener(env_, config);
75     return ERR_OK;
76 }
77 
InitAwaitTimeout(napi_env env,napi_value config)78 void JsStartupConfig::InitAwaitTimeout(napi_env env, napi_value config)
79 {
80     napi_value awaitTimeout = nullptr;
81     napi_get_named_property(env, config, "timeoutMs", &awaitTimeout);
82     if (awaitTimeout == nullptr) {
83         TAG_LOGD(AAFwkTag::STARTUP, "timeoutMs invalid");
84         return;
85     }
86     int32_t awaitTimeoutNum = DEFAULT_AWAIT_TIMEOUT_MS;
87     if (!ConvertFromJsValue(env, awaitTimeout, awaitTimeoutNum)) {
88         TAG_LOGD(AAFwkTag::STARTUP, "covert failed");
89         return;
90     }
91     if (awaitTimeoutNum <= 0) {
92         TAG_LOGE(AAFwkTag::STARTUP, "invalid argc");
93         awaitTimeoutNum = DEFAULT_AWAIT_TIMEOUT_MS;
94     }
95     TAG_LOGD(AAFwkTag::STARTUP, "set awaitTimeoutMs to %{public}d", awaitTimeoutNum);
96     awaitTimeoutMs_ = awaitTimeoutNum;
97 }
98 
InitListener(napi_env env,napi_value config)99 void JsStartupConfig::InitListener(napi_env env, napi_value config)
100 {
101     napi_value listener = nullptr;
102     napi_get_named_property(env, config, "startupListener", &listener);
103     if (listener == nullptr) {
104         TAG_LOGD(AAFwkTag::STARTUP, "null startupListener");
105         return;
106     }
107     if (!CheckTypeForNapiValue(env, listener, napi_object)) {
108         TAG_LOGD(AAFwkTag::STARTUP, "not napi object");
109         return;
110     }
111 
112     napi_value onCompleted = nullptr;
113     napi_get_named_property(env, listener, "onCompleted", &onCompleted);
114     if (onCompleted == nullptr) {
115         TAG_LOGD(AAFwkTag::STARTUP, "null onCompleted");
116         return;
117     }
118     napi_ref listenerRef = nullptr;
119     napi_create_reference(env, listener, 1, &listenerRef);
120     std::shared_ptr<NativeReference> listenerRefSp(reinterpret_cast<NativeReference *>(listenerRef));
121     OnCompletedCallbackFunc onCompletedCallback =
122         [env, listenerRefSp](const std::shared_ptr<StartupTaskResult> &result) {
123             if (env == nullptr || listenerRefSp == nullptr) {
124                 TAG_LOGE(AAFwkTag::STARTUP, "env or listenerRefSp null");
125                 return;
126             }
127             HandleScope handleScope(env);
128             napi_value listener = listenerRefSp->GetNapiValue();
129 
130             napi_value onCompleted = nullptr;
131             napi_get_named_property(env, listener, "onCompleted", &onCompleted);
132             if (onCompleted == nullptr) {
133                 TAG_LOGE(AAFwkTag::STARTUP, "null onCompleted");
134                 return;
135             }
136             bool isCallable = false;
137             napi_is_callable(env, onCompleted, &isCallable);
138             if (!isCallable) {
139                 TAG_LOGE(AAFwkTag::STARTUP, "onCompleted not callable");
140                 return;
141             }
142             napi_value argv[1] = { JsStartupConfig::BuildResult(env, result) };
143             napi_call_function(env, listener, onCompleted, 1, argv, nullptr);
144         };
145     listener_ = std::make_shared<StartupListener>(onCompletedCallback);
146 }
147 
BuildResult(napi_env env,const std::shared_ptr<StartupTaskResult> & result)148 napi_value JsStartupConfig::BuildResult(napi_env env, const std::shared_ptr<StartupTaskResult> &result)
149 {
150     if (result == nullptr) {
151         return CreateJsError(env, ERR_STARTUP_INTERNAL_ERROR,
152             StartupUtils::GetErrorMessage(ERR_STARTUP_INTERNAL_ERROR));
153     }
154     if (result->GetResultCode() != ERR_OK) {
155         return CreateJsError(env, result->GetResultCode(), result->GetResultMessage());
156     }
157     return CreateJsNull(env);
158 }
159 } // namespace AbilityRuntime
160 } // namespace OHOS
161