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 "napi_business_error.h"
17 
18 #include <cstring>
19 #include <string>
20 #include <unordered_map>
21 
22 #include "app_log_wrapper.h"
23 #include "napi_value.h"
24 
25 namespace OHOS {
26 namespace AppExecFwk {
27 namespace LIBZIP {
28 using namespace std;
29 
GenerateBusinessError(napi_env env,int32_t errCode,string errMsg)30 static napi_value GenerateBusinessError(napi_env env, int32_t errCode, string errMsg)
31 {
32     napi_value businessError = nullptr;
33     napi_value code = nullptr;
34     napi_value msg = nullptr;
35     code = NapiValue::CreateInt32(env, errCode).val_;
36     msg = NapiValue::CreateUTF8String(env, errMsg).val_;
37     napi_create_error(env, nullptr, msg, &businessError);
38     napi_set_named_property(env, businessError, ZLIB_TAG_ERR_CODE.c_str(), code);
39     napi_set_named_property(env, businessError, ZLIB_TAG_ERR_MSG.c_str(), msg);
40     return businessError;
41 }
42 
NapiBusinessError()43 NapiBusinessError::NapiBusinessError()
44 {}
45 
NapiBusinessError(ELegacy eLegacy)46 NapiBusinessError::NapiBusinessError(ELegacy eLegacy) : errno_(eLegacy), codingSystem_(ERR_CODE_SYSTEM_LEGACY)
47 {}
48 
NapiBusinessError(int32_t ePosix)49 NapiBusinessError::NapiBusinessError(int32_t ePosix) : errno_(ePosix), codingSystem_(ERR_CODE_SYSTEM_POSIX)
50 {}
51 
NapiBusinessError(int32_t ePosix,bool throwCode)52 NapiBusinessError::NapiBusinessError(int32_t ePosix, bool throwCode)
53     : errno_(ePosix), codingSystem_(ERR_CODE_SYSTEM_POSIX), throwCode_(throwCode)
54 {}
55 
56 NapiBusinessError::operator bool() const
57 {
58     return errno_ != ERRNO_NOERR;
59 }
60 
GetErrno(ErrCodeSystem cs)61 int32_t NapiBusinessError::GetErrno(ErrCodeSystem cs)
62 {
63     if (errno_ == ERRNO_NOERR) {
64         return ERRNO_NOERR;
65     }
66 
67     if (cs == codingSystem_) {
68         return errno_;
69     }
70 
71     if (cs == ERR_CODE_SYSTEM_POSIX) {
72         // Note that we should support more codes here
73         return EINVAL;
74     }
75 
76     // Note that this shall be done properly
77     return ELEGACY_INVAL;
78 }
79 
SetErrno(ELegacy eLegacy)80 void NapiBusinessError::SetErrno(ELegacy eLegacy)
81 {
82     errno_ = eLegacy;
83     codingSystem_ = ERR_CODE_SYSTEM_LEGACY;
84 }
85 
SetErrno(int32_t ePosix)86 void NapiBusinessError::SetErrno(int32_t ePosix)
87 {
88     errno_ = ePosix;
89     codingSystem_ = ERR_CODE_SYSTEM_POSIX;
90 }
91 
GetDefaultErrstr()92 std::string NapiBusinessError::GetDefaultErrstr()
93 {
94     if (codingSystem_ != ERR_CODE_SYSTEM_POSIX && codingSystem_ != ERR_CODE_SYSTEM_LEGACY) {
95         return "BUG: Curious coding system";
96     }
97     return strerror(GetErrno(ERR_CODE_SYSTEM_POSIX));
98 }
99 
GetNapiErr(napi_env env)100 napi_value NapiBusinessError::GetNapiErr(napi_env env)
101 {
102     int32_t errCode = GetErrno(codingSystem_);
103     if (errCode == ERRNO_NOERR) {
104         return nullptr;
105     }
106     if (!throwCode_) {
107         return GetNapiErr(env, GetDefaultErrstr());
108     }
109     int32_t code = 0;
110     string msg;
111     if (errCodeTable.find(errCode) != errCodeTable.end()) {
112         code = errCodeTable.at(errCode).first;
113         msg = errCodeTable.at(errCode).second;
114     } else {
115         code = errCodeTable.at(ENOSTR).first;
116         msg = errCodeTable.at(ENOSTR).second;
117     }
118     return GenerateBusinessError(env, code, msg);
119 }
120 
GetNapiErr(napi_env env,const string & errMsg)121 napi_value NapiBusinessError::GetNapiErr(napi_env env, const string &errMsg)
122 {
123     napi_value msg = NapiValue::CreateUTF8String(env, errMsg).val_;
124     napi_value res = nullptr;
125     napi_status createRes = napi_create_error(env, nullptr, msg, &res);
126     if (createRes) {
127         APP_LOGE("Failed to create an exception, errMsg = %{public}s", errMsg.c_str());
128     }
129     return res;
130 }
131 
ThrowErr(napi_env env)132 void NapiBusinessError::ThrowErr(napi_env env)
133 {
134     napi_value tmp = nullptr;
135     napi_get_and_clear_last_exception(env, &tmp);
136     int32_t code = 0;
137     string msg;
138     napi_status throwStatus = napi_ok;
139     if (errCodeTable.find(errno_) != errCodeTable.end()) {
140         code = errCodeTable.at(errno_).first;
141         msg = errCodeTable.at(errno_).second;
142     } else {
143         code = errCodeTable.at(ENOSTR).first;
144         msg = errCodeTable.at(ENOSTR).second;
145     }
146     if (!throwCode_) {
147         throwStatus = napi_throw_error(env, nullptr, msg.c_str());
148     } else {
149         throwStatus = napi_throw(env, GenerateBusinessError(env, code, msg));
150     }
151 
152     if (throwStatus != napi_ok) {
153         APP_LOGE("Failed to throw an exception, code = %{public}d, msg = %{public}s", throwStatus, msg.c_str());
154     }
155 }
156 
ThrowErr(napi_env env,int32_t code)157 void NapiBusinessError::ThrowErr(napi_env env, int32_t code)
158 {
159     napi_value tmp = nullptr;
160     napi_get_and_clear_last_exception(env, &tmp);
161     if (errCodeTable.find(code) == errCodeTable.end()) {
162         code = ENOSTR;
163     }
164     napi_status throwStatus =
165         napi_throw(env, GenerateBusinessError(env, errCodeTable.at(code).first, errCodeTable.at(code).second));
166     if (throwStatus != napi_ok) {
167         APP_LOGE("Failed to throw an exception, %{public}d, errMsg = %{public}s",
168             throwStatus,
169             errCodeTable.at(code).second.c_str());
170     }
171 }
172 
ThrowErr(napi_env env,const string & errMsg)173 void NapiBusinessError::ThrowErr(napi_env env, const string &errMsg)
174 {
175     napi_value tmp = nullptr;
176     napi_get_and_clear_last_exception(env, &tmp);
177     // Note that ace engine cannot throw errors created by napi_create_error so far
178     napi_status throwStatus = napi_throw_error(env, nullptr, errMsg.c_str());
179     if (throwStatus != napi_ok) {
180         APP_LOGE("Failed to throw an exception, %{public}d, errMsg = %{public}s", throwStatus, errMsg.c_str());
181     }
182 }
183 }  // namespace LIBZIP
184 }  // namespace AppExecFwk
185 }  // namespace OHOS