1 /*
2  * Copyright (c) 2022-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_quick_fix_manager.h"
17 
18 #include "hilog_tag_wrapper.h"
19 #include "js_application_quick_fix_info.h"
20 #include "js_runtime_utils.h"
21 #include "napi_common_util.h"
22 #include "quick_fix_error_utils.h"
23 #include "quick_fix_manager_client.h"
24 #include "js_error_utils.h"
25 
26 namespace OHOS {
27 namespace AbilityRuntime {
28 namespace {
29 constexpr size_t ARGC_ZERO = 0;
30 constexpr size_t ARGC_ONE = 1;
31 constexpr size_t ARGC_TWO = 2;
32 const char *QUICK_FIX_MANAGER_NAME = "JsQuickFixMgr";
33 } // namespace
34 
35 class JsQuickFixManager {
36 public:
37     JsQuickFixManager() = default;
38     ~JsQuickFixManager() = default;
39 
Finalizer(napi_env env,void * data,void * hint)40     static void Finalizer(napi_env env, void *data, void *hint)
41     {
42         TAG_LOGD(AAFwkTag::QUICKFIX, "called");
43         std::unique_ptr<JsQuickFixManager>(static_cast<JsQuickFixManager*>(data));
44     }
45 
ApplyQuickFix(napi_env env,napi_callback_info info)46     static napi_value ApplyQuickFix(napi_env env, napi_callback_info info)
47     {
48         GET_NAPI_INFO_AND_CALL(env, info, JsQuickFixManager, OnApplyQuickFix);
49     }
50 
GetApplyedQuickFixInfo(napi_env env,napi_callback_info info)51     static napi_value GetApplyedQuickFixInfo(napi_env env, napi_callback_info info)
52     {
53         GET_NAPI_INFO_AND_CALL(env, info, JsQuickFixManager, OnGetApplyedQuickFixInfo);
54     }
55 
RevokeQuickFix(napi_env env,napi_callback_info info)56     static napi_value RevokeQuickFix(napi_env env, napi_callback_info info)
57     {
58         GET_NAPI_INFO_AND_CALL(env, info, JsQuickFixManager, OnRevokeQuickFix);
59     }
60 
Throw(napi_env env,int32_t errCode)61     static void Throw(napi_env env, int32_t errCode)
62     {
63         auto externalErrCode = AAFwk::QuickFixErrorUtil::GetErrorCode(errCode);
64         auto errMsg = AAFwk::QuickFixErrorUtil::GetErrorMessage(errCode);
65         napi_value error = CreateJsError(env, externalErrCode, errMsg);
66         napi_throw(env, error);
67     }
68 
CreateJsErrorByErrorCode(napi_env env,int32_t errCode)69     static napi_value CreateJsErrorByErrorCode(napi_env env, int32_t errCode)
70     {
71         auto externalErrCode = AAFwk::QuickFixErrorUtil::GetErrorCode(errCode);
72         auto errMsg = AAFwk::QuickFixErrorUtil::GetErrorMessage(errCode);
73         return CreateJsError(env, externalErrCode, errMsg);
74     }
75 
76 private:
OnGetApplyedQuickFixInfo(napi_env env,NapiCallbackInfo & info)77     napi_value OnGetApplyedQuickFixInfo(napi_env env, NapiCallbackInfo &info)
78     {
79         TAG_LOGD(AAFwkTag::QUICKFIX, "called");
80         if (info.argc != ARGC_ONE && info.argc != ARGC_TWO) {
81             TAG_LOGE(AAFwkTag::QUICKFIX, "The number of parameter is invalid");
82             ThrowInvalidParamError(env, "Parameter error: The number of parameter is invalid.");
83             return CreateJsUndefined(env);
84         }
85 
86         std::string bundleName;
87         if (!OHOS::AppExecFwk::UnwrapStringFromJS2(env, info.argv[0], bundleName)) {
88             TAG_LOGE(AAFwkTag::QUICKFIX, "The bundleName is invalid");
89             ThrowInvalidParamError(env, "Parameter error: The bundleName is invalid, must be a string.");
90             return CreateJsUndefined(env);
91         }
92 
93         auto complete = [bundleName](napi_env env, NapiAsyncTask &task, int32_t status) {
94             AppExecFwk::ApplicationQuickFixInfo quickFixInfo;
95             auto errCode = DelayedSingleton<AAFwk::QuickFixManagerClient>::GetInstance()->GetApplyedQuickFixInfo(
96                 bundleName, quickFixInfo);
97             if (errCode == 0) {
98                 task.ResolveWithNoError(env, CreateJsApplicationQuickFixInfo(env, quickFixInfo));
99             } else {
100                 task.Reject(env, CreateJsErrorByErrorCode(env, errCode));
101             }
102         };
103 
104         napi_value lastParam = (info.argc == ARGC_ONE) ? nullptr : info.argv[1];
105         napi_value result = nullptr;
106         NapiAsyncTask::Schedule("JsQuickFixManager::OnGetApplyedQuickFixInfo", env,
107             CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
108         return result;
109     }
110 
OnApplyQuickFix(napi_env env,NapiCallbackInfo & info)111     napi_value OnApplyQuickFix(napi_env env, NapiCallbackInfo &info)
112     {
113         TAG_LOGD(AAFwkTag::QUICKFIX, "called");
114         if (info.argc != ARGC_ONE && info.argc != ARGC_TWO) {
115             TAG_LOGE(AAFwkTag::QUICKFIX, "The number of parameter is invalid");
116             ThrowInvalidParamError(env, "Parameter error: The number of parameter is invalid.");
117             return CreateJsUndefined(env);
118         }
119 
120         std::vector<std::string> hapQuickFixFiles;
121         if (!OHOS::AppExecFwk::UnwrapArrayStringFromJS(env, info.argv[0], hapQuickFixFiles)) {
122             TAG_LOGE(AAFwkTag::QUICKFIX, "Hap quick fix files is invalid");
123             ThrowInvalidParamError(env, "Parameter error: Hap quick fix files is invalid, must be a Array<string>.");
124             return CreateJsUndefined(env);
125         }
126 
127         auto complete = [hapQuickFixFiles](napi_env env, NapiAsyncTask &task, int32_t status) {
128             auto errcode = DelayedSingleton<AAFwk::QuickFixManagerClient>::GetInstance()->ApplyQuickFix(
129                 hapQuickFixFiles);
130             if (errcode == 0) {
131                 task.ResolveWithNoError(env, CreateJsUndefined(env));
132             } else {
133                 task.Reject(env, CreateJsErrorByErrorCode(env, errcode));
134             }
135         };
136 
137         napi_value lastParam = (info.argc == 1) ? nullptr : info.argv[1];
138         napi_value result = nullptr;
139         NapiAsyncTask::Schedule("JsQuickFixManager::OnApplyQuickFix", env,
140             CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
141         return result;
142     }
143 
OnRevokeQuickFix(napi_env env,NapiCallbackInfo & info)144     napi_value OnRevokeQuickFix(napi_env env, NapiCallbackInfo &info)
145     {
146         TAG_LOGD(AAFwkTag::QUICKFIX, "called");
147         if (info.argc == ARGC_ZERO) {
148             TAG_LOGE(AAFwkTag::QUICKFIX, "The number of parameter is invalid");
149             ThrowInvalidParamError(env, "Parameter error: The number of parameter is invalid.");
150             return CreateJsUndefined(env);
151         }
152 
153         std::string bundleName;
154         if (!ConvertFromJsValue(env, info.argv[ARGC_ZERO], bundleName)) {
155             TAG_LOGE(AAFwkTag::QUICKFIX, "The bundleName is invalid");
156             ThrowInvalidParamError(env, "Parameter error: The bundleName is invalid, must be a string.");
157             return CreateJsUndefined(env);
158         }
159 
160         std::shared_ptr<int32_t> errCode = std::make_shared<int32_t>(AAFwk::ERR_OK);
161         auto execute = [retval = errCode, bundleName] () {
162             auto quickFixMgr = DelayedSingleton<AAFwk::QuickFixManagerClient>::GetInstance();
163             if (quickFixMgr == nullptr) {
164                 *retval = AAFwk::ERR_QUICKFIX_INTERNAL_ERROR;
165                 TAG_LOGE(AAFwkTag::QUICKFIX, "mgr is nullptr");
166                 return;
167             }
168 
169             *retval = quickFixMgr->RevokeQuickFix(bundleName);
170             TAG_LOGD(AAFwkTag::QUICKFIX, "Revoke quick fix execute retval is {%{public}d}", *retval);
171         };
172 
173         auto complete = [retval = errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
174             TAG_LOGD(AAFwkTag::QUICKFIX, "Revoke quick fix complete called");
175             if (*retval != AAFwk::ERR_OK) {
176                 TAG_LOGE(AAFwkTag::QUICKFIX, "Revoke quick fix execution failed. retval is %{public}d", *retval);
177                 task.Reject(env, CreateJsErrorByErrorCode(env, *retval));
178                 return;
179             }
180             TAG_LOGD(AAFwkTag::QUICKFIX, "Revoke quick fix complete called ok");
181             task.ResolveWithNoError(env, CreateJsUndefined(env));
182         };
183 
184         napi_value lastParam = (info.argc == ARGC_ONE) ? nullptr : info.argv[ARGC_ONE];
185         napi_value result = nullptr;
186         NapiAsyncTask::Schedule("JsQuickFixManager::OnRevokeQuickFix", env,
187             CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
188         TAG_LOGD(AAFwkTag::QUICKFIX, "Function finished");
189         return result;
190     }
191 };
192 
CreateJsQuickFixManager(napi_env env,napi_value exportObj)193 napi_value CreateJsQuickFixManager(napi_env env, napi_value exportObj)
194 {
195     TAG_LOGD(AAFwkTag::QUICKFIX, "called");
196     if (env == nullptr || exportObj == nullptr) {
197         TAG_LOGE(AAFwkTag::QUICKFIX, "Input parameter is invalid");
198         return nullptr;
199     }
200 
201     std::unique_ptr<JsQuickFixManager> quickFixManager = std::make_unique<JsQuickFixManager>();
202     napi_wrap(env, exportObj, quickFixManager.release(), JsQuickFixManager::Finalizer, nullptr, nullptr);
203 
204     BindNativeFunction(env, exportObj, "applyQuickFix", QUICK_FIX_MANAGER_NAME, JsQuickFixManager::ApplyQuickFix);
205     BindNativeFunction(env, exportObj, "getApplicationQuickFixInfo", QUICK_FIX_MANAGER_NAME,
206         JsQuickFixManager::GetApplyedQuickFixInfo);
207     BindNativeFunction(env, exportObj, "revokeQuickFix", QUICK_FIX_MANAGER_NAME, JsQuickFixManager::RevokeQuickFix);
208     return CreateJsUndefined(env);
209 }
210 } // namespace AbilityRuntime
211 } // namespace OHOS
212