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