1  /*
2   * Copyright (C) 2022 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  #ifndef NAPI_UTILS_H
17  #define NAPI_UTILS_H
18  
19  #include <map>
20  #include <memory>
21  #include <string>
22  
23  #include "js_native_api.h"
24  #include "napi/native_api.h"
25  #include "napi/native_node_api.h"
26  #include "time_hilog.h"
27  namespace OHOS {
28  namespace MiscServices {
29  namespace Time {
30  #define NAPI_ASSERTS_BASE_RETURN(env, assertion, code, message, retVal) \
31      do {                                                         \
32          if (!(assertion)) {                                      \
33              NapiUtils::ThrowError(env, message, code);           \
34              return retVal;                                       \
35          }                                                        \
36      } while (0)
37  
38  #define NAPI_ASSERTP_RETURN(env, assertion, message) \
39      NAPI_ASSERTS_BASE_RETURN(env, assertion, ERROR, message, nullptr)
40  
41  /* check condition related to argc/argv, return and logging. */
42  #define CHECK_ARGS_RETURN_VOID(module, context, condition, message, code)                                   \
43      do {                                                                                                    \
44          if (!(condition)) {                                                                                 \
45              (context)->status = napi_invalid_arg;                                                           \
46              (context)->errMessage = std::string(message);                                                   \
47              (context)->errCode = code;                                                                      \
48              TIME_HILOGE(module, "test (" #condition ") failed: %{public}s", (context)->errMessage.c_str()); \
49              return;                                                                                         \
50          }                                                                                                   \
51      } while (0)
52  
53  #define CHECK_STATUS_RETURN_VOID(module, context, message, code)                        \
54      do {                                                                                \
55          if ((context)->status != napi_ok) {                                             \
56              (context)->errMessage = std::string(message);                               \
57              (context)->errCode = code;                                                  \
58              TIME_HILOGE(module, "test (context->status == napi_ok) failed: %{public}s", \
59                  (context)->errMessage.c_str());                                         \
60              return;                                                                     \
61          }                                                                               \
62      } while (0)
63  
64  /* check condition, return and logging if condition not true. */
65  #define CHECK_RETURN(module, condition, message, retVal)                   \
66      do {                                                                   \
67          if (!(condition)) {                                                \
68              TIME_HILOGE(module, "test (" #condition ") failed: " message); \
69              return retVal;                                                 \
70          }                                                                  \
71      } while (0)
72  
73  #define CHECK_RETURN_VOID(module, condition, message)                      \
74      do {                                                                   \
75          if (!(condition)) {                                                \
76              TIME_HILOGE(module, "test (" #condition ") failed: " message); \
77              return;                                                        \
78          }                                                                  \
79      } while (0)
80  
81  constexpr size_t ARGC_ZERO = 0;
82  constexpr size_t ARGC_ONE = 1;
83  constexpr size_t ARGC_TWO = 2;
84  constexpr size_t ARGC_THREE = 3;
85  
86  constexpr size_t ARGV_FIRST = 0;
87  constexpr size_t ARGV_SECOND = 1;
88  constexpr size_t ARGV_THIRD = 2;
89  
90  constexpr int32_t SET_TIME_MAX_PARA = 2;
91  constexpr int32_t SET_TIMEZONE_MAX_PARA = 2;
92  
93  constexpr int32_t CREATE_MAX_PARA = 2;
94  constexpr int32_t START_MAX_PARA = 3;
95  constexpr int32_t STOP_MAX_PARA = 2;
96  constexpr int32_t DESTROY_MAX_PARA = 2;
97  
98  constexpr int32_t MAX_TIME_ZONE_ID = 1024;
99  constexpr int32_t INVALID_TIME = -1;
100  
101  enum JsErrorCode : int32_t {
102      ERROR_OK = 0,
103      ERROR = -1,
104      PERMISSION_ERROR = 201,
105      SYSTEM_APP_ERROR = 202,
106      PARAMETER_ERROR = 401,
107      NTP_UPDATE_ERROR = 13000001,
108      NTP_NOT_UPDATE_ERROR = 13000002,
109  };
110  
111  struct CallbackPromiseInfo {
112      napi_ref callback = nullptr;
113      napi_deferred deferred = nullptr;
114      bool isCallback = false;
115      int errorCode = JsErrorCode::ERROR_OK;
116      std::string message;
117  };
118  
119  const std::map<int32_t, std::string> CODE_TO_MESSAGE = {
120      { JsErrorCode::SYSTEM_APP_ERROR, "Permission verification failed. A non-system application calls a system API" },
121      { JsErrorCode::PARAMETER_ERROR, "Parameter error" },
122      { JsErrorCode::PERMISSION_ERROR, "Permission denied" },
123      { JsErrorCode::ERROR, "Parameter check failed, permission denied, or system error." },
124  };
125  
126  class NapiUtils {
127  public:
128      static napi_value GetCallbackErrorValue(napi_env env, int32_t errCode, const std::string &message);
129      static napi_value NapiGetNull(napi_env env);
130      static void SetPromise(napi_env env, const napi_deferred deferred, int errorCode, const std::string &message,
131          napi_value result);
132      static void SetCallback(napi_env env, napi_ref callbackIn, int32_t errorCode, const std::string &message,
133          napi_value result);
134      static void ReturnCallbackPromise(napi_env env, const CallbackPromiseInfo &info, napi_value result);
135      static napi_value JSParaError(napi_env env, napi_ref callback);
136      static napi_value ParseParametersBySetTime(napi_env env, const napi_value (&argv)[SET_TIME_MAX_PARA], size_t argc,
137          int64_t &times, napi_ref &callback);
138      static napi_value ParseParametersBySetTimezone(napi_env env, const napi_value (&argv)[SET_TIMEZONE_MAX_PARA],
139          size_t argc, std::string &timezoneId, napi_ref &callback);
140      static napi_value ParseParametersGet(napi_env env, const napi_value (&argv)[SET_TIMEZONE_MAX_PARA], size_t argc,
141          napi_ref &callback);
142      static napi_value ParseParametersGetNA(napi_env env, const napi_value (&argv)[SET_TIMEZONE_MAX_PARA], size_t argc,
143          napi_ref &callback, bool *isNano);
144      static int32_t ConvertErrorCode(int32_t timeErrorCode);
145      static napi_value CreateNapiNumber(napi_env env, int32_t objName);
146      static napi_value GetUndefinedValue(napi_env env);
147      static napi_status GetValue(napi_env env, napi_value in, std::string &out);
148      static napi_status ThrowError(napi_env env, const char *napiMessage, int32_t napiCode);
149      static std::string GetErrorMessage(int32_t errCode);
150  };
151  } // namespace Time
152  } // namespace MiscServices
153  } // namespace OHOS
154  
155  #endif // NAPI_UTILS_H