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