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 "cm_napi_open_dialog.h"
17
18 #include "syspara/parameters.h"
19 #include "securec.h"
20
21 #include "cert_manager_api.h"
22 #include "cm_log.h"
23 #include "iservice_registry.h"
24 #include "bundle_mgr_proxy.h"
25 #include "system_ability_definition.h"
26
27 #include "cm_napi_dialog_common.h"
28 #include "want.h"
29 #include "want_params_wrapper.h"
30
31 namespace CMNapi {
32
33 class CmInstallUIExtensionCallback : public CmUIExtensionCallback {
34 public:
CmInstallUIExtensionCallback(std::shared_ptr<CmUIExtensionRequestContext> & reqContext)35 explicit CmInstallUIExtensionCallback(
36 std::shared_ptr<CmUIExtensionRequestContext>& reqContext) : CmUIExtensionCallback(reqContext)
37 {
38 this->reqContext_ = reqContext;
39 }
40
~CmInstallUIExtensionCallback()41 ~CmInstallUIExtensionCallback() override
42 {
43 CM_LOG_D("~CmInstallUIExtensionCallback");
44 }
45
OnRelease(const int32_t releaseCode)46 void OnRelease(const int32_t releaseCode) override
47 {
48 CM_LOG_D("InstallUIExtensionComponent OnRelease(), releaseCode = %d", releaseCode);
49 if (SetErrorCode(CMR_DIALOG_ERROR_OPERATION_CANCELS)) {
50 SendMessageBack();
51 }
52 }
53
OnResult(const int32_t resultCode,const OHOS::AAFwk::Want & result)54 void OnResult(const int32_t resultCode, const OHOS::AAFwk::Want& result) override
55 {
56 CM_LOG_D("InstallUIExtensionComponent OnResult(), resultCode = %d", resultCode);
57 this->resultCode_ = resultCode;
58 this->resultWant_ = result;
59 if (SetErrorCode(CMR_DIALOG_ERROR_INSTALL_FAILED)) {
60 SendMessageBack();
61 }
62 }
63
OnReceive(const OHOS::AAFwk::WantParams & request)64 void OnReceive(const OHOS::AAFwk::WantParams& request) override
65 {
66 CM_LOG_D("InstallUIExtensionComponent OnReceive()");
67 this->reqContext_->uri = request.GetStringParam("uri");
68 if (SetErrorCode(0)) {
69 SendMessageBack();
70 }
71 }
72
ProcessCallback(napi_env env,const CommonAsyncContext * asyncContext)73 void ProcessCallback(napi_env env, const CommonAsyncContext* asyncContext) override
74 {
75 napi_value args = nullptr;
76 if (asyncContext->errCode == CM_SUCCESS) {
77 NAPI_CALL_RETURN_VOID(env,
78 napi_create_string_utf8(env, asyncContext->uri.c_str(), NAPI_AUTO_LENGTH, &args));
79 } else {
80 args = GenerateBusinessError(env, asyncContext->errCode);
81 }
82
83 if (asyncContext->deferred != nullptr) {
84 if (asyncContext->errCode == CM_SUCCESS) {
85 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncContext->deferred, args));
86 } else {
87 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncContext->deferred, args));
88 }
89 }
90 }
91
OnDestroy()92 void OnDestroy() override
93 {
94 CM_LOG_D("InstallUIExtensionComponent OnDestroy()");
95 }
96
97 private:
SetErrorCode(int32_t errCode)98 bool SetErrorCode(int32_t errCode)
99 {
100 if (this->reqContext_ == nullptr) {
101 CM_LOG_E("OnError reqContext is nullptr");
102 return false;
103 }
104 if (this->alreadyCallback_) {
105 CM_LOG_D("alreadyCallback");
106 return false;
107 }
108 this->alreadyCallback_ = true;
109 this->reqContext_->errCode = errCode;
110 return true;
111 };
112 int32_t resultCode_ = 0;
113 OHOS::AAFwk::Want resultWant_;
114 std::shared_ptr<CmUIExtensionRequestContext> reqContext_ = nullptr;
115 bool alreadyCallback_ = false;
116 };
117
IsCmCertificateScopeEnum(const uint32_t value)118 static bool IsCmCertificateScopeEnum(const uint32_t value)
119 {
120 switch (static_cast<CertificateScope>(value)) {
121 case CertificateScope::CURRENT_USER:
122 return true;
123 default:
124 return false;
125 }
126 }
127
IsCmCertificateTypeAndConvert(const uint32_t value,uint32_t & pageType)128 static bool IsCmCertificateTypeAndConvert(const uint32_t value, uint32_t &pageType)
129 {
130 switch (static_cast<CmCertificateType>(value)) {
131 case CmCertificateType::CA_CERT:
132 pageType = CmDialogPageType::PAGE_INSTALL_CA_GUIDE;
133 return true;
134 default:
135 return false;
136 }
137 }
138
CMCheckArgvAndInitContext(std::shared_ptr<CmUIExtensionRequestContext> asyncContext,napi_value argv[],size_t length)139 static napi_value CMCheckArgvAndInitContext(std::shared_ptr<CmUIExtensionRequestContext> asyncContext,
140 napi_value argv[], size_t length)
141 {
142 if (length != PARAM_SIZE_FOUR) {
143 CM_LOG_E("params number vaild failed");
144 return nullptr;
145 }
146 // Parse first argument for context.
147 if (!ParseCmUIAbilityContextReq(asyncContext->env, argv[PARAM0], asyncContext->context)) {
148 CM_LOG_E("ParseUIAbilityContextReq failed");
149 return nullptr;
150 }
151
152 // Parse second argument for certificate type.
153 uint32_t certificateType = 0;
154 if (ParseUint32(asyncContext->env, argv[PARAM1], certificateType) == nullptr) {
155 CM_LOG_E("parse type failed");
156 return nullptr;
157 }
158 if (!IsCmCertificateTypeAndConvert(certificateType, asyncContext->certificateType)) {
159 CM_LOG_E("certificateType invalid");
160 return nullptr;
161 }
162
163 // Parse third argument for certificateScope.
164 if (ParseUint32(asyncContext->env, argv[PARAM2], asyncContext->certificateScope) == nullptr) {
165 CM_LOG_E("parse type failed");
166 return nullptr;
167 }
168 if (!IsCmCertificateScopeEnum(asyncContext->certificateScope)) {
169 CM_LOG_E("certificateScope invalid");
170 return nullptr;
171 }
172
173 // Parse fourth argument for cert.
174 if (GetUint8ArrayToBase64Str(asyncContext->env, argv[PARAM3], asyncContext->certStr) == nullptr) {
175 CM_LOG_E("cert is not a uint8Array or the length is 0 or too long.");
176 return nullptr;
177 }
178 return GetInt32(asyncContext->env, 0);
179 }
180
CMGetInstallCertWant(std::shared_ptr<CmUIExtensionRequestContext> asyncContext)181 static OHOS::AAFwk::Want CMGetInstallCertWant(std::shared_ptr<CmUIExtensionRequestContext> asyncContext)
182 {
183 OHOS::AAFwk::Want want;
184 want.SetElementName(CERT_MANAGER_BUNDLENAME, CERT_MANAGER_ABILITYNAME);
185 want.SetParam(CERT_MANAGER_PAGE_TYPE, static_cast<int32_t>(asyncContext->certificateType));
186 want.SetParam(CERT_MANAGER_CERTIFICATE_DATA, asyncContext->certStr);
187 want.SetParam(CERT_MANAGER_CERTSCOPE_TYPE, static_cast<int32_t>(asyncContext->certificateScope));
188 want.SetParam(CERT_MANAGER_CALLER_BUNDLENAME, asyncContext->labelName);
189 want.SetParam(PARAM_UI_EXTENSION_TYPE, SYS_COMMON_UI);
190 return want;
191 }
192
GetBundleMgrProxy()193 static OHOS::sptr<OHOS::AppExecFwk::BundleMgrProxy> GetBundleMgrProxy()
194 {
195 auto systemAbilityManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
196 if (!systemAbilityManager) {
197 CM_LOG_E("fail to get system ability mgr.");
198 return nullptr;
199 }
200
201 auto remoteObject = systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
202 if (!remoteObject) {
203 CM_LOG_E("fail to get bundle manager proxy.");
204 return nullptr;
205 }
206 return OHOS::iface_cast<OHOS::AppExecFwk::BundleMgrProxy>(remoteObject);
207 }
208
GetCallerLabelName(std::shared_ptr<CmUIExtensionRequestContext> asyncContext)209 static int32_t GetCallerLabelName(std::shared_ptr<CmUIExtensionRequestContext> asyncContext)
210 {
211 OHOS::sptr<OHOS::AppExecFwk::BundleMgrProxy> bundleMgrProxy = GetBundleMgrProxy();
212 if (bundleMgrProxy == nullptr) {
213 CM_LOG_E("Failed to get bundle manager proxy.");
214 return CM_FAILURE;
215 }
216
217 OHOS::AppExecFwk::BundleInfo bundleInfo;
218 int32_t flags = static_cast<int32_t>(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_DEFAULT) |
219 static_cast<int32_t>(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION) |
220 static_cast<int32_t>(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_HAP_MODULE) |
221 static_cast<int32_t>(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_ABILITY);
222 int32_t resCode = bundleMgrProxy->GetBundleInfoForSelf(flags, bundleInfo);
223 if (resCode != CM_SUCCESS) {
224 CM_LOG_E("Failed to get bundleInfo, resCode is %d", resCode);
225 return CM_FAILURE;
226 }
227
228 if (asyncContext->context->GetResourceManager() == nullptr) {
229 CM_LOG_E("context get resourcemanager faild");
230 return CMR_ERROR_NULL_POINTER;
231 }
232
233 resCode = asyncContext->context->GetResourceManager()->GetStringById(bundleInfo.applicationInfo.labelId,
234 asyncContext->labelName);
235 if (resCode != CM_SUCCESS) {
236 CM_LOG_E("getStringById is faild, resCode is %d", resCode);
237 return CM_FAILURE;
238 }
239 return CM_SUCCESS;
240 }
241
CMNapiOpenInstallCertDialog(napi_env env,napi_callback_info info)242 napi_value CMNapiOpenInstallCertDialog(napi_env env, napi_callback_info info)
243 {
244 CM_LOG_D("cert install dialog enter");
245 napi_value result = nullptr;
246 NAPI_CALL(env, napi_get_undefined(env, &result));
247 if (OHOS::system::GetParameter("const.product.devicetype", "") != "2in1") {
248 CM_LOG_E("deviceType is not 2in1");
249 std::string errMsg = "DeviceType Error. deviceType is not 2in1";
250 ThrowError(env, DIALOG_ERROR_NOT_SUPPORTED, errMsg);
251 return result;
252 }
253
254 size_t argc = PARAM_SIZE_FOUR;
255 napi_value argv[PARAM_SIZE_FOUR] = { nullptr };
256 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
257 if (argc != PARAM_SIZE_FOUR) {
258 CM_LOG_E("params number mismatch");
259 std::string errMsg = "Parameter Error. Params number mismatch, need " + std::to_string(PARAM_SIZE_FOUR)
260 + ", given " + std::to_string(argc);
261 ThrowError(env, PARAM_ERROR, errMsg);
262 return result;
263 }
264
265 auto asyncContext = std::make_shared<CmUIExtensionRequestContext>(env);
266 asyncContext->env = env;
267 if (CMCheckArgvAndInitContext(asyncContext, argv, sizeof(argv) / sizeof(argv[0])) == nullptr) {
268 CM_LOG_E("check argv vaild and init faild");
269 ThrowError(env, PARAM_ERROR, "check argv vaild and init faild");
270 return nullptr;
271 }
272
273 if (GetCallerLabelName(asyncContext) != CM_SUCCESS) {
274 CM_LOG_E("get caller labelName faild");
275 ThrowError(env, DIALOG_ERROR_GENERIC, "get caller labelName faild");
276 return nullptr;
277 }
278 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &result));
279
280 auto uiExtCallback = std::make_shared<CmInstallUIExtensionCallback>(asyncContext);
281 StartUIExtensionAbility(asyncContext, CMGetInstallCertWant(asyncContext), uiExtCallback);
282 CM_LOG_D("cert install dialog end");
283 return result;
284 }
285 } // namespace CMNapi
286
287