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 #include "napi_common_util.h"
21 #include "napi_common_want.h"
22
23 namespace OHOS {
24 namespace AbilityRuntime {
25
JsStartupConfig(napi_env env)26 JsStartupConfig::JsStartupConfig(napi_env env) : StartupConfig(), env_(env)
27 {}
28
29 JsStartupConfig::~JsStartupConfig() = default;
30
Init(std::unique_ptr<NativeReference> & configEntryJsRef,std::shared_ptr<AAFwk::Want> want)31 int32_t JsStartupConfig::Init(std::unique_ptr<NativeReference> &configEntryJsRef,
32 std::shared_ptr<AAFwk::Want> want)
33 {
34 if (configEntryJsRef == nullptr) {
35 TAG_LOGE(AAFwkTag::STARTUP, "null configEntry");
36 return ERR_STARTUP_INTERNAL_ERROR;
37 }
38 HandleScope handleScope(env_);
39
40 napi_value configEntry = configEntryJsRef->GetNapiValue();
41 if (!CheckTypeForNapiValue(env_, configEntry, napi_object)) {
42 TAG_LOGE(AAFwkTag::STARTUP, "not napi object");
43 return ERR_STARTUP_INTERNAL_ERROR;
44 }
45 napi_value onConfig = nullptr;
46 napi_get_named_property(env_, configEntry, "onConfig", &onConfig);
47 if (onConfig == nullptr) {
48 TAG_LOGE(AAFwkTag::STARTUP, "null onConfig");
49 return ERR_STARTUP_INTERNAL_ERROR;
50 }
51 bool isCallable = false;
52 napi_is_callable(env_, onConfig, &isCallable);
53 if (!isCallable) {
54 TAG_LOGE(AAFwkTag::STARTUP, "onConfig not callable");
55 return ERR_STARTUP_INTERNAL_ERROR;
56 }
57 napi_value config = nullptr;
58 napi_call_function(env_, configEntry, onConfig, 0, nullptr, &config);
59 if (config == nullptr) {
60 TAG_LOGE(AAFwkTag::STARTUP, "null config");
61 return ERR_STARTUP_INTERNAL_ERROR;
62 }
63
64 InitAwaitTimeout(env_, config);
65 InitListener(env_, config);
66 InitCustomization(env_, configEntry, want);
67 return ERR_OK;
68 }
69
Init(napi_value config)70 int32_t JsStartupConfig::Init(napi_value config)
71 {
72 if (config == nullptr) {
73 TAG_LOGE(AAFwkTag::STARTUP, "null config");
74 return ERR_STARTUP_INTERNAL_ERROR;
75 }
76
77 InitAwaitTimeout(env_, config);
78 InitListener(env_, config);
79 return ERR_OK;
80 }
81
InitAwaitTimeout(napi_env env,napi_value config)82 void JsStartupConfig::InitAwaitTimeout(napi_env env, napi_value config)
83 {
84 napi_value awaitTimeout = nullptr;
85 napi_get_named_property(env, config, "timeoutMs", &awaitTimeout);
86 if (awaitTimeout == nullptr) {
87 TAG_LOGD(AAFwkTag::STARTUP, "timeoutMs invalid");
88 return;
89 }
90 int32_t awaitTimeoutNum = DEFAULT_AWAIT_TIMEOUT_MS;
91 if (!ConvertFromJsValue(env, awaitTimeout, awaitTimeoutNum)) {
92 TAG_LOGD(AAFwkTag::STARTUP, "covert failed");
93 return;
94 }
95 if (awaitTimeoutNum <= 0) {
96 TAG_LOGE(AAFwkTag::STARTUP, "invalid argc");
97 awaitTimeoutNum = DEFAULT_AWAIT_TIMEOUT_MS;
98 }
99 TAG_LOGD(AAFwkTag::STARTUP, "set awaitTimeoutMs to %{public}d", awaitTimeoutNum);
100 awaitTimeoutMs_ = awaitTimeoutNum;
101 }
102
InitListener(napi_env env,napi_value config)103 void JsStartupConfig::InitListener(napi_env env, napi_value config)
104 {
105 napi_value listener = nullptr;
106 napi_get_named_property(env, config, "startupListener", &listener);
107 if (listener == nullptr) {
108 TAG_LOGD(AAFwkTag::STARTUP, "null startupListener");
109 return;
110 }
111 if (!CheckTypeForNapiValue(env, listener, napi_object)) {
112 TAG_LOGD(AAFwkTag::STARTUP, "not napi object");
113 return;
114 }
115
116 napi_value onCompleted = nullptr;
117 napi_get_named_property(env, listener, "onCompleted", &onCompleted);
118 if (onCompleted == nullptr) {
119 TAG_LOGD(AAFwkTag::STARTUP, "null onCompleted");
120 return;
121 }
122 napi_ref listenerRef = nullptr;
123 napi_create_reference(env, listener, 1, &listenerRef);
124 std::shared_ptr<NativeReference> listenerRefSp(reinterpret_cast<NativeReference *>(listenerRef));
125 OnCompletedCallbackFunc onCompletedCallback =
126 [env, listenerRefSp](const std::shared_ptr<StartupTaskResult> &result) {
127 if (env == nullptr || listenerRefSp == nullptr) {
128 TAG_LOGE(AAFwkTag::STARTUP, "null env or listenerRefSp");
129 return;
130 }
131 HandleScope handleScope(env);
132 napi_value listener = listenerRefSp->GetNapiValue();
133
134 napi_value onCompleted = nullptr;
135 napi_get_named_property(env, listener, "onCompleted", &onCompleted);
136 if (onCompleted == nullptr) {
137 TAG_LOGE(AAFwkTag::STARTUP, "null onCompleted");
138 return;
139 }
140 bool isCallable = false;
141 napi_is_callable(env, onCompleted, &isCallable);
142 if (!isCallable) {
143 TAG_LOGE(AAFwkTag::STARTUP, "onCompleted not callable");
144 return;
145 }
146 napi_value argv[1] = { JsStartupConfig::BuildResult(env, result) };
147 napi_call_function(env, listener, onCompleted, 1, argv, nullptr);
148 };
149 listener_ = std::make_shared<StartupListener>(onCompletedCallback);
150 }
151
InitCustomization(napi_env env,napi_value configEntry,std::shared_ptr<AAFwk::Want> want)152 void JsStartupConfig::InitCustomization(napi_env env, napi_value configEntry, std::shared_ptr<AAFwk::Want> want)
153 {
154 TAG_LOGD(AAFwkTag::STARTUP, "InitCustomization");
155 if (!want) {
156 TAG_LOGD(AAFwkTag::STARTUP, "want is null");
157 return;
158 }
159
160 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, *want);
161 napi_value method = nullptr;
162 napi_get_named_property(env, configEntry, "onRequestCustomMatchRule", &method);
163 if (method == nullptr) {
164 TAG_LOGE(AAFwkTag::APPKIT, "null method onRequestCustomMatchRule");
165 return;
166 }
167
168 bool isCallable = false;
169 napi_is_callable(env, method, &isCallable);
170 if (!isCallable) {
171 TAG_LOGI(AAFwkTag::STARTUP, "onRequestCustomMatchRule not callable");
172 return;
173 }
174
175 constexpr size_t argc = 1;
176 napi_value argv[] = { napiWant };
177 napi_value callResult = nullptr;
178 napi_status status = napi_call_function(env, configEntry, method, argc, argv, &callResult);
179 if (status != napi_ok) {
180 TAG_LOGE(AAFwkTag::ABILITYMGR, "call js func onRequestCustomMatchRule failed: %{public}d", status);
181 }
182 customization_ = AppExecFwk::UnwrapStringFromJS(env, callResult);
183 }
184
BuildResult(napi_env env,const std::shared_ptr<StartupTaskResult> & result)185 napi_value JsStartupConfig::BuildResult(napi_env env, const std::shared_ptr<StartupTaskResult> &result)
186 {
187 if (result == nullptr) {
188 return CreateJsError(env, ERR_STARTUP_INTERNAL_ERROR,
189 StartupUtils::GetErrorMessage(ERR_STARTUP_INTERNAL_ERROR));
190 }
191 if (result->GetResultCode() != ERR_OK) {
192 return CreateJsError(env, result->GetResultCode(), result->GetResultMessage());
193 }
194 return CreateJsNull(env);
195 }
196 } // namespace AbilityRuntime
197 } // namespace OHOS
198