1 /*
2 * Copyright (c) 2021-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 "common.h"
17 #include "ans_inner_errors.h"
18 #include "ans_log_wrapper.h"
19 #include "js_native_api.h"
20 #include "js_native_api_types.h"
21 #include "napi_common.h"
22 #include "napi_common_util.h"
23 #include "notification_action_button.h"
24 #include "notification_capsule.h"
25 #include "notification_constant.h"
26 #include "notification_progress.h"
27 #include "notification_time.h"
28 #include "pixel_map_napi.h"
29
30 namespace OHOS {
31 namespace NotificationNapi {
32 const uint32_t MAX_PARAM_NUM = 5;
33
34 namespace {
35 static const std::unordered_map<int32_t, std::string> ERROR_CODE_MESSAGE {
36 {ERROR_PERMISSION_DENIED, "Permission denied"},
37 {ERROR_NOT_SYSTEM_APP, "The application isn't system application"},
38 {ERROR_PARAM_INVALID, "Invalid parameter"},
39 {ERROR_SYSTEM_CAP_ERROR, "SystemCapability not found"},
40 {ERROR_INTERNAL_ERROR, "Internal error"},
41 {ERROR_IPC_ERROR, "Marshalling or unmarshalling error"},
42 {ERROR_SERVICE_CONNECT_ERROR, "Failed to connect to the service"},
43 {ERROR_NOTIFICATION_CLOSED, "Notification disabled"},
44 {ERROR_SLOT_CLOSED, "Notification slot disabled"},
45 {ERROR_NOTIFICATION_UNREMOVABLE, "Notification deletion disabled"},
46 {ERROR_NOTIFICATION_NOT_EXIST, "The notification does not exist"},
47 {ERROR_USER_NOT_EXIST, "The user does not exist"},
48 {ERROR_OVER_MAX_NUM_PER_SECOND, "The notification sending frequency reaches the upper limit"},
49 {ERROR_DISTRIBUTED_OPERATION_FAILED, "Distributed operation failed"},
50 {ERROR_READ_TEMPLATE_CONFIG_FAILED, "Failed to read the template configuration"},
51 {ERROR_NO_MEMORY, "No memory space"},
52 {ERROR_BUNDLE_NOT_FOUND, "The specified bundle name was not found"},
53 {ERROR_NO_AGENT_SETTING, "There is no corresponding agent relationship configuration"},
54 {ERROR_DIALOG_IS_POPPING, "Dialog is popping"},
55 {ERROR_SETTING_WINDOW_EXIST, "The notification settings window is already displayed"},
56 {ERROR_NO_PROFILE_TEMPLATE, "Not exit noNotDisturb profile template"},
57 {ERROR_REPEAT_SET, "Repeat create or end"},
58 {ERROR_NO_RIGHT, "No permission"},
59 {ERROR_EXPIRED_NOTIFICATION, "Low update version"},
60 {ERROR_NETWORK_UNREACHABLE, "Network unreachable"},
61 {ERROR_REJECTED_WITH_DISABLE_NOTIFICATION,
62 "The application is not allowed to publish notifications due to permission control settings"},
63 {ERROR_DISTRIBUTED_OPERATION_TIMEOUT, "Distributed operation timeout"},
64 };
65 }
66
NapiGetBoolean(napi_env env,const bool & isValue)67 napi_value Common::NapiGetBoolean(napi_env env, const bool &isValue)
68 {
69 napi_value result = nullptr;
70 napi_get_boolean(env, isValue, &result);
71 return result;
72 }
73
NapiGetNull(napi_env env)74 napi_value Common::NapiGetNull(napi_env env)
75 {
76 napi_value result = nullptr;
77 napi_get_null(env, &result);
78 return result;
79 }
80
NapiGetUndefined(napi_env env)81 napi_value Common::NapiGetUndefined(napi_env env)
82 {
83 napi_value result = nullptr;
84 napi_get_undefined(env, &result);
85 return result;
86 }
87
CreateErrorValue(napi_env env,int32_t errCode,bool newType)88 napi_value Common::CreateErrorValue(napi_env env, int32_t errCode, bool newType)
89 {
90 ANS_LOGI("enter, errorCode[%{public}d]", errCode);
91 napi_value error = Common::NapiGetNull(env);
92 if (errCode == ERR_OK && newType) {
93 return error;
94 }
95
96 napi_value code = nullptr;
97 napi_create_int32(env, errCode, &code);
98
99 auto iter = ERROR_CODE_MESSAGE.find(errCode);
100 std::string errMsg = iter != ERROR_CODE_MESSAGE.end() ? iter->second : "";
101 napi_value message = nullptr;
102 napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
103
104 napi_create_error(env, nullptr, message, &error);
105 napi_set_named_property(env, error, "code", code);
106 return error;
107 }
108
CreateErrorValue(napi_env env,int32_t errCode,std::string & msg)109 napi_value Common::CreateErrorValue(napi_env env, int32_t errCode, std::string &msg)
110 {
111 ANS_LOGI("enter, errorCode[%{public}d]", errCode);
112 napi_value error = Common::NapiGetNull(env);
113 if (errCode == ERR_OK) {
114 return error;
115 }
116
117 napi_value code = nullptr;
118 napi_create_int32(env, errCode, &code);
119
120 auto iter = ERROR_CODE_MESSAGE.find(errCode);
121 std::string errMsg = iter != ERROR_CODE_MESSAGE.end() ? iter->second : "";
122 napi_value message = nullptr;
123 napi_create_string_utf8(env, errMsg.append(" ").append(msg).c_str(), NAPI_AUTO_LENGTH, &message);
124
125 napi_create_error(env, nullptr, message, &error);
126 napi_set_named_property(env, error, "code", code);
127 return error;
128 }
129
NapiThrow(napi_env env,int32_t errCode)130 void Common::NapiThrow(napi_env env, int32_t errCode)
131 {
132 ANS_LOGD("enter");
133
134 napi_throw(env, CreateErrorValue(env, errCode, true));
135 }
136
NapiThrow(napi_env env,int32_t errCode,std::string & msg)137 void Common::NapiThrow(napi_env env, int32_t errCode, std::string &msg)
138 {
139 ANS_LOGD("enter");
140
141 napi_throw(env, CreateErrorValue(env, errCode, msg));
142 }
143
GetCallbackErrorValue(napi_env env,int32_t errCode)144 napi_value Common::GetCallbackErrorValue(napi_env env, int32_t errCode)
145 {
146 napi_value result = nullptr;
147 napi_value eCode = nullptr;
148 NAPI_CALL(env, napi_create_int32(env, errCode, &eCode));
149 NAPI_CALL(env, napi_create_object(env, &result));
150 NAPI_CALL(env, napi_set_named_property(env, result, "code", eCode));
151 return result;
152 }
153
PaddingCallbackPromiseInfo(const napi_env & env,const napi_ref & callback,CallbackPromiseInfo & info,napi_value & promise)154 void Common::PaddingCallbackPromiseInfo(
155 const napi_env &env, const napi_ref &callback, CallbackPromiseInfo &info, napi_value &promise)
156 {
157 ANS_LOGD("enter");
158
159 if (callback) {
160 ANS_LOGD("Callback is not nullptr.");
161 info.callback = callback;
162 info.isCallback = true;
163 } else {
164 napi_deferred deferred = nullptr;
165 NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, &deferred, &promise));
166 info.deferred = deferred;
167 info.isCallback = false;
168 }
169 }
170
ReturnCallbackPromise(const napi_env & env,const CallbackPromiseInfo & info,const napi_value & result)171 void Common::ReturnCallbackPromise(const napi_env &env, const CallbackPromiseInfo &info, const napi_value &result)
172 {
173 ANS_LOGD("enter errorCode=%{public}d", info.errorCode);
174 if (info.isCallback) {
175 SetCallback(env, info.callback, info.errorCode, result, false);
176 } else {
177 SetPromise(env, info.deferred, info.errorCode, result, false);
178 }
179 ANS_LOGD("end");
180 }
181
SetCallback(const napi_env & env,const napi_ref & callbackIn,const int32_t & errorCode,const napi_value & result,bool newType)182 void Common::SetCallback(
183 const napi_env &env, const napi_ref &callbackIn, const int32_t &errorCode, const napi_value &result, bool newType)
184 {
185 ANS_LOGD("enter");
186 napi_value undefined = nullptr;
187 napi_get_undefined(env, &undefined);
188
189 napi_value callback = nullptr;
190 napi_value resultout = nullptr;
191 napi_get_reference_value(env, callbackIn, &callback);
192 napi_value results[ARGS_TWO] = {nullptr};
193 results[PARAM0] = CreateErrorValue(env, errorCode, newType);
194 results[PARAM1] = result;
195 napi_status napi_result = napi_call_function(env, undefined, callback, ARGS_TWO, &results[PARAM0], &resultout);
196 if (napi_result != napi_ok) {
197 ANS_LOGE("napi_call_function failed, result = %{public}d", napi_result);
198 }
199 NAPI_CALL_RETURN_VOID(env, napi_result);
200 ANS_LOGI("end");
201 }
202
SetCallback(const napi_env & env,const napi_ref & callbackIn,const napi_value & result)203 void Common::SetCallback(
204 const napi_env &env, const napi_ref &callbackIn, const napi_value &result)
205 {
206 ANS_LOGD("enter");
207 napi_value undefined = nullptr;
208 napi_get_undefined(env, &undefined);
209
210 napi_value callback = nullptr;
211 napi_value resultout = nullptr;
212 napi_get_reference_value(env, callbackIn, &callback);
213 napi_status napi_result = napi_call_function(env, undefined, callback, ARGS_ONE, &result, &resultout);
214 if (napi_result != napi_ok) {
215 ANS_LOGE("napi_call_function failed, result = %{public}d", napi_result);
216 }
217 NAPI_CALL_RETURN_VOID(env, napi_result);
218 ANS_LOGI("end");
219 }
220
SetCallbackArg2(const napi_env & env,const napi_ref & callbackIn,const napi_value & result0,const napi_value & result1)221 void Common::SetCallbackArg2(
222 const napi_env &env, const napi_ref &callbackIn, const napi_value &result0, const napi_value &result1)
223 {
224 ANS_LOGD("enter");
225 napi_value result[ARGS_TWO] = {result0, result1};
226 napi_value undefined = nullptr;
227 napi_get_undefined(env, &undefined);
228
229 napi_value callback = nullptr;
230 napi_value resultout = nullptr;
231 napi_get_reference_value(env, callbackIn, &callback);
232 napi_status napi_result = napi_call_function(env, undefined, callback, ARGS_TWO, result, &resultout);
233 if (napi_result != napi_ok) {
234 ANS_LOGE("napi_call_function failed, result = %{public}d", napi_result);
235 }
236 NAPI_CALL_RETURN_VOID(env, napi_result);
237 ANS_LOGI("end");
238 }
239
SetPromise(const napi_env & env,const napi_deferred & deferred,const int32_t & errorCode,const napi_value & result,bool newType)240 void Common::SetPromise(const napi_env &env,
241 const napi_deferred &deferred, const int32_t &errorCode, const napi_value &result, bool newType)
242 {
243 ANS_LOGD("enter");
244 if (errorCode == ERR_OK) {
245 napi_resolve_deferred(env, deferred, result);
246 } else {
247 napi_reject_deferred(env, deferred, CreateErrorValue(env, errorCode, newType));
248 }
249 ANS_LOGD("end");
250 }
251
JSParaError(const napi_env & env,const napi_ref & callback)252 napi_value Common::JSParaError(const napi_env &env, const napi_ref &callback)
253 {
254 if (callback) {
255 return Common::NapiGetNull(env);
256 }
257 napi_value promise = nullptr;
258 napi_deferred deferred = nullptr;
259 napi_create_promise(env, &deferred, &promise);
260 SetPromise(env, deferred, ERROR, Common::NapiGetNull(env), false);
261 return promise;
262 }
263
ParseParaOnlyCallback(const napi_env & env,const napi_callback_info & info,napi_ref & callback)264 napi_value Common::ParseParaOnlyCallback(const napi_env &env, const napi_callback_info &info, napi_ref &callback)
265 {
266 ANS_LOGD("enter");
267
268 size_t argc = ONLY_CALLBACK_MAX_PARA;
269 napi_value argv[ONLY_CALLBACK_MAX_PARA] = {nullptr};
270 napi_value thisVar = nullptr;
271 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
272 if (argc < ONLY_CALLBACK_MIN_PARA) {
273 ANS_LOGE("Wrong number of arguments");
274 Common::NapiThrow(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED);
275 return nullptr;
276 }
277
278 // argv[0]:callback
279 napi_valuetype valuetype = napi_undefined;
280 if (argc >= ONLY_CALLBACK_MAX_PARA) {
281 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
282 if (valuetype != napi_function) {
283 ANS_LOGE("Callback is not function excute promise.");
284 return Common::NapiGetNull(env);
285 }
286 napi_create_reference(env, argv[PARAM0], 1, &callback);
287 }
288
289 return Common::NapiGetNull(env);
290 }
291
CreateReturnValue(const napi_env & env,const CallbackPromiseInfo & info,const napi_value & result)292 void Common::CreateReturnValue(const napi_env &env, const CallbackPromiseInfo &info, const napi_value &result)
293 {
294 ANS_LOGD("enter errorCode=%{public}d", info.errorCode);
295 int32_t errorCode = info.errorCode == ERR_OK ? ERR_OK : ErrorToExternal(info.errorCode);
296 if (info.isCallback) {
297 SetCallback(env, info.callback, errorCode, result, true);
298 } else {
299 SetPromise(env, info.deferred, errorCode, result, true);
300 }
301 ANS_LOGD("end");
302 }
303
ErrorToExternal(uint32_t errCode)304 int32_t Common::ErrorToExternal(uint32_t errCode)
305 {
306 static std::vector<std::pair<uint32_t, int32_t>> errorsConvert = {
307 {ERR_ANS_PERMISSION_DENIED, ERROR_PERMISSION_DENIED},
308 {ERR_ANS_NON_SYSTEM_APP, ERROR_NOT_SYSTEM_APP},
309 {ERR_ANS_NOT_SYSTEM_SERVICE, ERROR_NOT_SYSTEM_APP},
310 {ERR_ANS_INVALID_PARAM, ERROR_PARAM_INVALID},
311 {ERR_ANS_INVALID_UID, ERROR_PARAM_INVALID},
312 {ERR_ANS_ICON_OVER_SIZE, ERROR_PARAM_INVALID},
313 {ERR_ANS_PICTURE_OVER_SIZE, ERROR_PARAM_INVALID},
314 {ERR_ANS_PUSH_CHECK_EXTRAINFO_INVALID, ERROR_PARAM_INVALID},
315 {ERR_ANS_NO_MEMORY, ERROR_NO_MEMORY},
316 {ERR_ANS_TASK_ERR, ERROR_INTERNAL_ERROR},
317 {ERR_ANS_PARCELABLE_FAILED, ERROR_IPC_ERROR},
318 {ERR_ANS_TRANSACT_FAILED, ERROR_IPC_ERROR},
319 {ERR_ANS_REMOTE_DEAD, ERROR_IPC_ERROR},
320 {ERR_ANS_SERVICE_NOT_READY, ERROR_SERVICE_CONNECT_ERROR},
321 {ERR_ANS_SERVICE_NOT_CONNECTED, ERROR_SERVICE_CONNECT_ERROR},
322 {ERR_ANS_NOT_ALLOWED, ERROR_NOTIFICATION_CLOSED},
323 {ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_ENABLED, ERROR_SLOT_CLOSED},
324 {ERR_ANS_NOTIFICATION_IS_UNREMOVABLE, ERROR_NOTIFICATION_UNREMOVABLE},
325 {ERR_ANS_NOTIFICATION_NOT_EXISTS, ERROR_NOTIFICATION_NOT_EXIST},
326 {ERR_ANS_GET_ACTIVE_USER_FAILED, ERROR_USER_NOT_EXIST},
327 {ERR_ANS_INVALID_PID, ERROR_BUNDLE_NOT_FOUND},
328 {ERR_ANS_INVALID_BUNDLE, ERROR_BUNDLE_NOT_FOUND},
329 {ERR_ANS_OVER_MAX_ACTIVE_PERSECOND, ERROR_OVER_MAX_NUM_PER_SECOND},
330 {ERR_ANS_OVER_MAX_UPDATE_PERSECOND, ERROR_OVER_MAX_NUM_PER_SECOND},
331 {ERR_ANS_DISTRIBUTED_OPERATION_FAILED, ERROR_DISTRIBUTED_OPERATION_FAILED},
332 {ERR_ANS_DISTRIBUTED_GET_INFO_FAILED, ERROR_DISTRIBUTED_OPERATION_FAILED},
333 {ERR_ANS_PREFERENCES_NOTIFICATION_READ_TEMPLATE_CONFIG_FAILED, ERROR_READ_TEMPLATE_CONFIG_FAILED},
334 {ERR_ANS_REPEAT_CREATE, ERROR_REPEAT_SET},
335 {ERR_ANS_END_NOTIFICATION, ERROR_REPEAT_SET},
336 {ERR_ANS_EXPIRED_NOTIFICATION, ERROR_EXPIRED_NOTIFICATION},
337 {ERR_ANS_PUSH_CHECK_FAILED, ERROR_NO_RIGHT},
338 {ERR_ANS_PUSH_CHECK_UNREGISTERED, ERROR_NO_RIGHT},
339 {ERR_ANS_PUSH_CHECK_NETWORK_UNREACHABLE, ERROR_NETWORK_UNREACHABLE},
340 {ERR_ANS_NO_AGENT_SETTING, ERROR_NO_AGENT_SETTING},
341 {ERR_ANS_DIALOG_IS_POPPING, ERROR_DIALOG_IS_POPPING},
342 {ERR_ANS_NO_PROFILE_TEMPLATE, ERROR_NO_PROFILE_TEMPLATE},
343 {ERR_ANS_REJECTED_WITH_DISABLE_NOTIFICATION, ERROR_REJECTED_WITH_DISABLE_NOTIFICATION},
344 {ERR_ANS_OPERATION_TIMEOUT, ERROR_DISTRIBUTED_OPERATION_TIMEOUT},
345 };
346
347 int32_t ExternalCode = ERROR_INTERNAL_ERROR;
348 for (const auto &errorConvert : errorsConvert) {
349 if (errCode == errorConvert.first) {
350 ExternalCode = errorConvert.second;
351 break;
352 }
353 }
354
355 ANS_LOGI("internal errorCode[%{public}u] to external errorCode[%{public}d]", errCode, ExternalCode);
356 return ExternalCode;
357 }
358
NapiReturnCapErrCb(napi_env env,napi_callback_info info)359 napi_value Common::NapiReturnCapErrCb(napi_env env, napi_callback_info info)
360 {
361 size_t argc = MAX_PARAM_NUM;
362 napi_value argv[MAX_PARAM_NUM] = {nullptr};
363 napi_value thisVar = nullptr;
364 napi_ref callback = nullptr;
365 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
366 for (size_t i = 0; i < argc && i < MAX_PARAM_NUM; ++i) {
367 napi_valuetype valuetype = napi_undefined;
368 NAPI_CALL(env, napi_typeof(env, argv[i], &valuetype));
369 if (valuetype == napi_function) {
370 napi_create_reference(env, argv[i], 1, &callback);
371 SetCallback(env, callback, ERROR_SYSTEM_CAP_ERROR, nullptr, false);
372 napi_delete_reference(env, callback);
373 return NapiGetNull(env);
374 }
375 }
376
377 return NapiReturnCapErr(env, info);
378 }
379
NapiReturnCapErr(napi_env env,napi_callback_info info)380 napi_value Common::NapiReturnCapErr(napi_env env, napi_callback_info info)
381 {
382 napi_value promise = nullptr;
383 napi_deferred deferred = nullptr;
384 napi_create_promise(env, &deferred, &promise);
385 SetPromise(env, deferred, ERROR_SYSTEM_CAP_ERROR, Common::NapiGetNull(env), false);
386 return promise;
387 }
388
NapiReturnFalseCb(napi_env env,napi_callback_info info)389 napi_value Common::NapiReturnFalseCb(napi_env env, napi_callback_info info)
390 {
391 return Common::NapiReturnFalseCbInner(env, info, false);
392 }
393
NapiReturnFalseCbNewType(napi_env env,napi_callback_info info)394 napi_value Common::NapiReturnFalseCbNewType(napi_env env, napi_callback_info info)
395 {
396 return Common::NapiReturnFalseCbInner(env, info, true);
397 }
398
NapiReturnFalseCbInner(napi_env env,napi_callback_info info,bool newType)399 napi_value Common::NapiReturnFalseCbInner(napi_env env, napi_callback_info info, bool newType)
400 {
401 size_t argc = ONLY_CALLBACK_MAX_PARA;
402 napi_value argv[ONLY_CALLBACK_MAX_PARA] = {nullptr};
403 napi_value thisVar = nullptr;
404 napi_ref callback = nullptr;
405 napi_value result = nullptr;
406 napi_get_boolean(env, false, &result);
407 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
408 if (argc >= ONLY_CALLBACK_MIN_PARA) {
409 napi_valuetype valuetype = napi_undefined;
410 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
411 if (valuetype == napi_function) {
412 napi_create_reference(env, argv[PARAM0], 1, &callback);
413 SetCallback(env, callback, 0, result, true);
414 napi_delete_reference(env, callback);
415 return NapiGetNull(env);
416 }
417 }
418 napi_value promise = nullptr;
419 napi_deferred deferred = nullptr;
420 napi_create_promise(env, &deferred, &promise);
421 SetPromise(env, deferred, 0, result, false);
422 return promise;
423 }
424 } // namespace NotificationNapi
425 } // namespace OHOS
426