• 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 "cm_napi_open_dialog.h"
17 
18 #include "securec.h"
19 
20 #include "cert_manager_api.h"
21 #include "cm_log.h"
22 
23 #include "cm_napi_dialog_common.h"
24 #include "want.h"
25 #include "want_params_wrapper.h"
26 
27 namespace CMNapi {
28 namespace {
29 const std::string PARAM_UI_EXTENSION_TYPE = "ability.want.params.uiExtensionType";
30 const std::string SYS_COMMON_UI = "sys/commonUI";
31 const std::string CERT_MANAGER_BUNDLENAME = "com.ohos.certmanager";
32 const std::string CERT_MANAGER_ABILITYNAME = "CertPickerUIExtAbility";
33 const std::string CERT_MANAGER_PAGE_TYPE = "pageType";
34 constexpr int32_t PARAM0 = 0;
35 constexpr int32_t PARAM1 = 1;
36 constexpr int32_t PARAM_SIZE_TWO = 2;
37 } // namespace
38 
CommonAsyncContext(napi_env env)39 CommonAsyncContext::CommonAsyncContext(napi_env env)
40 {
41     CM_LOG_D("CommonAsyncContext");
42     this->env = env;
43 }
44 
~CommonAsyncContext()45 CommonAsyncContext::~CommonAsyncContext()
46 {
47     CM_LOG_D("~CommonAsyncContext");
48 }
49 
CmUIExtensionCallback(std::shared_ptr<CmUIExtensionRequestContext> & reqContext)50 CmUIExtensionCallback::CmUIExtensionCallback(std::shared_ptr<CmUIExtensionRequestContext>& reqContext)
51 {
52     this->reqContext_ = reqContext;
53 }
54 
SetSessionId(const int32_t sessionId)55 void CmUIExtensionCallback::SetSessionId(const int32_t sessionId)
56 {
57     this->sessionId_ = sessionId;
58 }
59 
SetErrorCode(int32_t code)60 bool CmUIExtensionCallback::SetErrorCode(int32_t code)
61 {
62     if (this->reqContext_ == nullptr) {
63         CM_LOG_E("OnError reqContext is nullptr");
64         return false;
65     }
66     if (this->alreadyCallback_) {
67         CM_LOG_D("alreadyCallback");
68         return false;
69     }
70     this->alreadyCallback_ = true;
71     this->reqContext_->errCode = code;
72     return true;
73 }
74 
OnRelease(const int32_t releaseCode)75 void CmUIExtensionCallback::OnRelease(const int32_t releaseCode)
76 {
77     CM_LOG_D("UIExtensionComponent OnRelease(), releaseCode = %d", releaseCode);
78     if (SetErrorCode(releaseCode)) {
79         SendMessageBack();
80     }
81 }
82 
OnResult(const int32_t resultCode,const OHOS::AAFwk::Want & result)83 void CmUIExtensionCallback::OnResult(const int32_t resultCode, const OHOS::AAFwk::Want& result)
84 {
85     CM_LOG_D("UIExtensionComponent OnResult(), resultCode = %d", resultCode);
86     this->resultCode_ = resultCode;
87     this->resultWant_ = result;
88     if (SetErrorCode(0)) {
89         SendMessageBack();
90     }
91 }
92 
OnReceive(const OHOS::AAFwk::WantParams & request)93 void CmUIExtensionCallback::OnReceive(const OHOS::AAFwk::WantParams& request)
94 {
95     CM_LOG_D("UIExtensionComponent OnReceive()");
96     if (SetErrorCode(0)) {
97         SendMessageBack();
98     }
99 }
100 
OnError(const int32_t errorCode,const std::string & name,const std::string & message)101 void CmUIExtensionCallback::OnError(const int32_t errorCode, const std::string& name, const std::string& message)
102 {
103     CM_LOG_E("UIExtensionComponent OnError(), errorCode = %d, name = %s, message = %s",
104         errorCode, name.c_str(), message.c_str());
105     if (SetErrorCode(errorCode)) {
106         SendMessageBack();
107     }
108 }
109 
OnRemoteReady(const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy> & uiProxy)110 void CmUIExtensionCallback::OnRemoteReady(const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy>& uiProxy)
111 {
112     CM_LOG_D("UIExtensionComponent OnRemoteReady()");
113 }
114 
OnDestroy()115 void CmUIExtensionCallback::OnDestroy()
116 {
117     CM_LOG_D("UIExtensionComponent OnDestroy()");
118     if (SetErrorCode(0)) {
119         SendMessageBack();
120     }
121 }
122 
ProcessCallback(napi_env env,const CommonAsyncContext * asyncContext)123 void ProcessCallback(napi_env env, const CommonAsyncContext* asyncContext)
124 {
125     napi_value args[PARAM_SIZE_TWO] = {nullptr};
126 
127     if (asyncContext->errCode == CM_SUCCESS) {
128         NAPI_CALL_RETURN_VOID(env, napi_create_uint32(env, 0, &args[PARAM0]));
129         NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, true, &args[PARAM1]));
130     } else {
131         args[PARAM0] = GenerateBusinessError(env, asyncContext->errCode);
132         NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &args[PARAM1]));
133     }
134 
135     if (asyncContext->deferred != nullptr) {
136         GeneratePromise(env, asyncContext->deferred, asyncContext->errCode, args, CM_ARRAY_SIZE(args));
137     }
138 }
139 
SendMessageBack()140 void CmUIExtensionCallback::SendMessageBack()
141 {
142     CM_LOG_I("start SendMessageBack");
143     if (this->reqContext_ == nullptr) {
144         CM_LOG_E("reqContext is nullptr");
145         return;
146     }
147 
148     auto abilityContext = this->reqContext_->context;
149     if (abilityContext != nullptr) {
150         auto uiContent = abilityContext->GetUIContent();
151         if (uiContent != nullptr) {
152             CM_LOG_D("CloseModalUIExtension");
153             uiContent->CloseModalUIExtension(this->sessionId_);
154         }
155     }
156 
157     CM_LOG_D("ProcessCallback");
158     ProcessCallback(this->reqContext_->env, this->reqContext_.get());
159 }
160 
ParseCmUIAbilityContextReq(napi_env env,const napi_value & obj,std::shared_ptr<OHOS::AbilityRuntime::AbilityContext> & abilityContext)161 bool ParseCmUIAbilityContextReq(
162     napi_env env, const napi_value& obj, std::shared_ptr<OHOS::AbilityRuntime::AbilityContext>& abilityContext)
163 {
164     bool stageMode = false;
165     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, obj, stageMode);
166     if (status != napi_ok || !stageMode) {
167         CM_LOG_E("not stage mode");
168         return false;
169     }
170 
171     auto context = OHOS::AbilityRuntime::GetStageModeContext(env, obj);
172     if (context == nullptr) {
173         CM_LOG_E("get context failed");
174         return false;
175     }
176 
177     abilityContext = OHOS::AbilityRuntime::Context::ConvertTo<OHOS::AbilityRuntime::AbilityContext>(context);
178     if (abilityContext == nullptr) {
179         CM_LOG_E("get abilityContext failed");
180         return false;
181     }
182     CM_LOG_I("end ParseUIAbilityContextReq");
183     return true;
184 }
185 
StartUIExtensionAbility(std::shared_ptr<CmUIExtensionRequestContext> asyncContext,OHOS::AAFwk::Want want)186 static void StartUIExtensionAbility(std::shared_ptr<CmUIExtensionRequestContext> asyncContext,
187     OHOS::AAFwk::Want want)
188 {
189     CM_LOG_D("begin StartUIExtensionAbility");
190     auto abilityContext = asyncContext->context;
191     if (abilityContext == nullptr) {
192         CM_LOG_E("abilityContext is null");
193         ThrowError(asyncContext->env, PARAM_ERROR, "abilityContext is null");
194         return;
195     }
196     auto uiContent = abilityContext->GetUIContent();
197     if (uiContent == nullptr) {
198         CM_LOG_E("uiContent is null");
199         ThrowError(asyncContext->env, PARAM_ERROR, "uiContent is null");
200         return;
201     }
202 
203     auto uiExtCallback = std::make_shared<CmUIExtensionCallback>(asyncContext);
204     OHOS::Ace::ModalUIExtensionCallbacks extensionCallbacks = {
205         [uiExtCallback](int32_t releaseCode) { uiExtCallback->OnRelease(releaseCode); },
206         [uiExtCallback](int32_t resultCode, const OHOS::AAFwk::Want& result) {
207             uiExtCallback->OnResult(resultCode, result); },
208         [uiExtCallback](const OHOS::AAFwk::WantParams& request) { uiExtCallback->OnReceive(request); },
209         [uiExtCallback](int32_t errorCode, const std::string& name, const std::string& message) {
210             uiExtCallback->OnError(errorCode, name, message); },
211         [uiExtCallback](const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy>& uiProxy) {
212             uiExtCallback->OnRemoteReady(uiProxy); },
213         [uiExtCallback]() { uiExtCallback->OnDestroy(); }
214     };
215 
216     OHOS::Ace::ModalUIExtensionConfig uiExtConfig;
217     uiExtConfig.isProhibitBack = false;
218     int32_t sessionId = uiContent->CreateModalUIExtension(want, extensionCallbacks, uiExtConfig);
219     CM_LOG_I("end CreateModalUIExtension");
220     if (sessionId == 0) {
221         CM_LOG_E("CreateModalUIExtension failed");
222         ThrowError(asyncContext->env, PARAM_ERROR, "CreateModalUIExtension failed");
223     }
224     uiExtCallback->SetSessionId(sessionId);
225     return;
226 }
227 
IsCmDialogPageTypeEnum(const uint32_t value)228 static bool IsCmDialogPageTypeEnum(const uint32_t value)
229 {
230     switch (static_cast<CmDialogPageType>(value)) {
231         case CmDialogPageType::PAGE_MAIN:
232         case CmDialogPageType::PAGE_CA_CERTIFICATE:
233         case CmDialogPageType::PAGE_CREDENTIAL:
234         case CmDialogPageType::PAGE_INSTALL_CERTIFICATE:
235             return true;
236         default:
237             return false;
238     }
239 }
240 
CMNapiOpenCertManagerDialog(napi_env env,napi_callback_info info)241 napi_value CMNapiOpenCertManagerDialog(napi_env env, napi_callback_info info)
242 {
243     CM_LOG_I("cert manager dialog enter");
244     size_t argc = PARAM_SIZE_TWO;
245     napi_value argv[PARAM_SIZE_TWO] = { nullptr };
246     napi_value result = nullptr;
247     NAPI_CALL(env, napi_get_undefined(env, &result));
248     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
249     if (argc != PARAM_SIZE_TWO) {
250         CM_LOG_E("params number mismatch");
251         std::string errMsg = "Parameter Error. Params number mismatch, need " + std::to_string(PARAM_SIZE_TWO)
252             + ", given " + std::to_string(argc);
253         ThrowError(env, PARAM_ERROR, errMsg);
254         return result;
255     }
256 
257     // Parse first argument for context.
258     auto asyncContext = std::make_shared<CmUIExtensionRequestContext>(env);
259     if (!ParseCmUIAbilityContextReq(env, argv[PARAM0], asyncContext->context)) {
260         CM_LOG_E("ParseUIAbilityContextReq failed");
261         ThrowError(env, PARAM_ERROR, "Get context failed.");
262         return result;
263     }
264 
265     // Parse second argument for page type.
266     result = ParseUint32(env, argv[PARAM1], asyncContext->pageType);
267     if (result == nullptr) {
268         CM_LOG_E("parse type failed");
269         ThrowError(env, PARAM_ERROR, "parse type failed");
270         return result;
271     }
272 
273     if (!IsCmDialogPageTypeEnum(asyncContext->pageType)) {
274         CM_LOG_E("pageType invalid");
275         ThrowError(env, PARAM_ERROR, "pageType invalid");
276         return nullptr;
277     }
278 
279     asyncContext->env = env;
280     OHOS::AAFwk::Want want;
281     want.SetElementName(CERT_MANAGER_BUNDLENAME, CERT_MANAGER_ABILITYNAME);
282     want.SetParam(CERT_MANAGER_PAGE_TYPE, static_cast<int32_t>(asyncContext->pageType));
283     want.SetParam(PARAM_UI_EXTENSION_TYPE, SYS_COMMON_UI);
284     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &result));
285 
286     // Start ui extension by context.
287     StartUIExtensionAbility(asyncContext, want);
288     CM_LOG_D("cert manager dialog end");
289     return result;
290 }
291 }  // namespace CMNapi
292 
293