1 /*
2 * Copyright (c) 2021 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 "properties.h"
17 #include "hilog_common.h"
18
19 #include "napi/native_api.h"
20 #include "napi/native_node_api.h"
21 #include "../../common/napi/n_func_arg.h"
22 #include "../../common/napi/n_class.h"
23 #include "hilog/log.h"
24 #include "hilog/log_c.h"
25 #include "securec.h"
26 #include "../include/context/hilog_napi_base.h"
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 namespace OHOS {
32 namespace HiviewDFX {
33 using namespace std;
34 #define DEFAULT_LOG_TYPE LOG_APP
35 const HiLogLabel LABEL = { LOG_CORE, 0xD002D00, "Hilog_JS" };
36 static constexpr int MIN_NUMBER = 3;
37 static constexpr int MAX_NUMBER = 100;
38 static constexpr int PUBLIC_LEN = 6;
39 static constexpr int PRIVATE_LEN = 7;
40 static constexpr int PROPERTY_POS = 2;
41 static const string PRIV_STR = "<private>";
42
ParseLogContent(string & formatStr,vector<napiParam> & params,string & logContent)43 void ParseLogContent(string& formatStr, vector<napiParam>& params, string& logContent)
44 {
45 string& ret = logContent;
46 if (params.empty()) {
47 ret += formatStr;
48 return;
49 }
50 auto size = params.size();
51 auto len = formatStr.size();
52 uint32_t pos = 0;
53 uint32_t count = 0;
54 bool debug = true;
55 #if not (defined(__WINDOWS__) || defined(__MAC__) || defined(__LINUX__))
56 debug = IsDebugOn();
57 #endif
58 bool priv = (!debug) && IsPrivateSwitchOn();
59 for (; pos < len; ++pos) {
60 bool showPriv = true;
61 if (count >= size) {
62 break;
63 }
64 if (formatStr[pos] != '%') {
65 ret += formatStr[pos];
66 continue;
67 }
68
69 if (((pos + PUBLIC_LEN + PROPERTY_POS) < len) &&
70 formatStr.substr(pos + PROPERTY_POS, PUBLIC_LEN) == "public") {
71 pos += (PUBLIC_LEN + PROPERTY_POS);
72 showPriv = false;
73 } else if (((pos + PRIVATE_LEN + PROPERTY_POS) < len) &&
74 formatStr.substr(pos + PROPERTY_POS, PRIVATE_LEN) == "private") {
75 pos += (PRIVATE_LEN + PROPERTY_POS);
76 }
77
78 if (pos + 1 >= len) {
79 break;
80 }
81 switch (formatStr[pos + 1]) {
82 case 'd':
83 case 'i':
84 if (params[count].type == napi_number || params[count].type == napi_bigint) {
85 ret += (priv && showPriv) ? PRIV_STR : params[count].val;
86 }
87 count++;
88 ++pos;
89 break;
90 case 's':
91 if (params[count].type == napi_string || params[count].type == napi_undefined ||
92 params[count].type == napi_boolean || params[count].type == napi_null) {
93 ret += (priv && showPriv) ? PRIV_STR : params[count].val;
94 }
95 count++;
96 ++pos;
97 break;
98 case 'O':
99 case 'o':
100 if (params[count].type == napi_object) {
101 ret += (priv && showPriv) ? PRIV_STR : params[count].val;
102 }
103 count++;
104 ++pos;
105 break;
106 case '%':
107 ret += formatStr[pos];
108 ++pos;
109 break;
110 default:
111 ret += formatStr[pos];
112 break;
113 }
114 }
115 if (pos < len) {
116 ret += formatStr.substr(pos, len - pos);
117 }
118 return;
119 }
120
isLoggable(napi_env env,napi_callback_info info)121 napi_value HilogNapiBase::isLoggable(napi_env env, napi_callback_info info)
122 {
123 NFuncArg funcArg(env, info);
124
125 if (!funcArg.InitArgs(NARG_CNT::THREE)) {
126 return nullptr;
127 }
128 bool succ = false;
129 int32_t domain;
130 tie(succ, domain) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
131 if (!succ) {
132 return nullptr;
133 }
134 if ((domain < static_cast<int32_t>(DOMAIN_APP_MIN)) || (domain > static_cast<int32_t>(DOMAIN_APP_MAX))) {
135 return NVal::CreateBool(env, false).val_;
136 }
137 int32_t level;
138 tie(succ, level) = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32();
139 if (!succ) {
140 return nullptr;
141 }
142 unique_ptr<char[]> tag;
143 tie(succ, tag, ignore) = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String();
144 if (!succ) {
145 return nullptr;
146 }
147 bool res = HiLogIsLoggable(domain, tag.get(), static_cast<LogLevel>(level));
148 return NVal::CreateBool(env, res).val_;
149 }
150
debug(napi_env env,napi_callback_info info)151 napi_value HilogNapiBase::debug(napi_env env, napi_callback_info info)
152 {
153 return HilogImpl(env, info, LOG_DEBUG);
154 }
155
info(napi_env env,napi_callback_info info)156 napi_value HilogNapiBase::info(napi_env env, napi_callback_info info)
157 {
158 return HilogImpl(env, info, LOG_INFO);
159 }
160
warn(napi_env env,napi_callback_info info)161 napi_value HilogNapiBase::warn(napi_env env, napi_callback_info info)
162 {
163 return HilogImpl(env, info, LOG_WARN);
164 }
165
error(napi_env env,napi_callback_info info)166 napi_value HilogNapiBase::error(napi_env env, napi_callback_info info)
167 {
168 return HilogImpl(env, info, LOG_ERROR);
169 }
170
fatal(napi_env env,napi_callback_info info)171 napi_value HilogNapiBase::fatal(napi_env env, napi_callback_info info)
172 {
173 return HilogImpl(env, info, LOG_FATAL);
174 }
175
parseNapiValue(napi_env env,napi_callback_info info,napi_value element,vector<napiParam> & params)176 napi_value HilogNapiBase::parseNapiValue(napi_env env, napi_callback_info info,
177 napi_value element, vector<napiParam>& params)
178 {
179 bool succ = false;
180 napi_valuetype type;
181 napiParam res = {napi_null, ""};
182 napi_status typeStatus = napi_typeof(env, element, &type);
183 unique_ptr<char[]> name;
184 if (typeStatus != napi_ok) {
185 return nullptr;
186 }
187 if (type == napi_number || type == napi_bigint || type == napi_object ||
188 type == napi_undefined || type == napi_boolean || type == napi_null) {
189 napi_value elmString;
190 napi_status objectStatus = napi_coerce_to_string(env, element, &elmString);
191 if (objectStatus != napi_ok) {
192 return nullptr;
193 }
194 tie(succ, name, ignore) = NVal(env, elmString).ToUTF8String();
195 if (!succ) {
196 return nullptr;
197 }
198 } else if (type == napi_string) {
199 tie(succ, name, ignore) = NVal(env, element).ToUTF8String();
200 if (!succ) {
201 return nullptr;
202 }
203 } else {
204 HiLog::Info(LABEL, "%{public}s", "type mismatch");
205 }
206 res.type = type;
207 if (name != nullptr) {
208 res.val = name.get();
209 }
210 params.emplace_back(res);
211 return nullptr;
212 }
213
HilogImpl(napi_env env,napi_callback_info info,int level)214 napi_value HilogNapiBase::HilogImpl(napi_env env, napi_callback_info info, int level)
215 {
216 NFuncArg funcArg(env, info);
217 funcArg.InitArgs(MIN_NUMBER, MAX_NUMBER);
218 bool succ = false;
219 int32_t domain;
220 tie(succ, domain) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
221 if (!succ) {
222 HiLog::Info(LABEL, "%{public}s", "domain mismatch");
223 return nullptr;
224 }
225 unique_ptr<char[]> tag;
226 tie(succ, tag, ignore) = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String();
227 if (!succ) {
228 HiLog::Info(LABEL, "%{public}s", "tag mismatch");
229 return nullptr;
230 }
231 unique_ptr<char[]> fmt;
232 tie(succ, fmt, ignore) = NVal(env, funcArg[NARG_POS::THIRD]).ToUTF8String();
233 if (!succ) {
234 HiLog::Info(LABEL, "%{public}s", "Format mismatch");
235 return nullptr;
236 }
237 string fmtString = fmt.get();
238 bool res = false;
239 napi_value array = funcArg[NARG_POS::FOURTH];
240 napi_is_array(env, array, &res);
241 string logContent;
242 vector<napiParam> params;
243 if (!res) {
244 for (size_t i = MIN_NUMBER; i < funcArg.GetArgc(); i++) {
245 napi_value argsVal = funcArg[i];
246 (void)parseNapiValue(env, info, argsVal, params);
247 }
248 } else {
249 if (funcArg.GetArgc() != MIN_NUMBER + 1) {
250 NAPI_ASSERT(env, false, "Argc mismatch");
251 HiLog::Info(LABEL, "%{public}s", "Argc mismatch");
252 return nullptr;
253 }
254 uint32_t length;
255 napi_status lengthStatus = napi_get_array_length(env, array, &length);
256 if (lengthStatus != napi_ok) {
257 return nullptr;
258 }
259 uint32_t i;
260 for (i = 0; i < length; i++) {
261 napi_value element;
262 napi_status eleStatus = napi_get_element(env, array, i, &element);
263 if (eleStatus != napi_ok) {
264 return nullptr;
265 }
266 (void)parseNapiValue(env, info, element, params);
267 }
268 }
269 ParseLogContent(fmtString, params, logContent);
270 HiLogPrint(DEFAULT_LOG_TYPE, static_cast<LogLevel>(level), domain, tag.get(), "%{public}s", logContent.c_str());
271 return nullptr;
272 }
273 } // namespace HiviewDFX
274 } // namespace OHOS
275
276 #ifdef __cplusplus
277 }
278 #endif
279