1 /*
2  * Copyright (c) 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 #ifndef NAPI_PARAM_UTILS_H
16 #define NAPI_PARAM_UTILS_H
17 
18 #include <cstdint>
19 #include <map>
20 #include <list>
21 #include <string>
22 #include <mutex>
23 #include <vector>
24 #include "napi/native_api.h"
25 #include "napi/native_common.h"
26 #include "napi/native_node_api.h"
27 #include "napi_base_context.h"
28 #include "drm_log.h"
29 #include "i_keysession_service.h"
30 
31 namespace OHOS {
32 namespace DrmStandard {
33 /* Constants for array index */
34 const int32_t PARAM0 = 0;
35 const int32_t PARAM1 = 1;
36 const int32_t PARAM2 = 2;
37 const int32_t PARAM3 = 3;
38 
39 /* Constants for array size */
40 const int32_t ARGS_ZERO = 0;
41 const int32_t ARGS_ONE = 1;
42 const int32_t ARGS_TWO = 2;
43 const int32_t ARGS_THREE = 3;
44 const int32_t ARGS_FOUR = 4;
45 
46 enum NapiMediaKeyRequestType {
47     MEDIA_KEY_REQUEST_TYPE_UNKNOWN = 0,
48     MEDIA_KEY_REQUEST_TYPE_INITIAL,
49     MEDIA_KEY_REQUEST_TYPE_RENEWAL,
50     MEDIA_KEY_REQUEST_TYPE_RELEASE,
51     MEDIA_KEY_REQUEST_TYPE_NONE,
52     MEDIA_KEY_REQUEST_TYPE_UPDATE,
53 };
54 
55 struct NapiProvisionRequest {
56     std::vector<uint8_t> data;
57     std::string defaultURL;
58 };
59 
60 struct DrmEventParame {
61     int32_t extra;
62     std::vector<uint8_t> data;
63 };
64 
65 struct DrmKeysChangeEventParame {
66     std::map<std::vector<uint8_t>, MediaKeySessionKeyStatus> statusTable;
67     bool hasNewGoodLicense;
68 };
69 
70 template<typename T>
71 class ObjectRefMap {
72 public:
73     static std::mutex allObjLock;
74     static std::map<T*, uint32_t> refMap;
75     static void Insert(T *obj);
76     static void Erase(T *obj);
77     static T *IncreaseRef(T *obj);
78     static void DecreaseRef(T *obj);
79 
80     ObjectRefMap(T *obj);
81     ~ObjectRefMap();
82     T *GetPtr();
83 
84 private:
85     T *obj_ = nullptr;
86 };
87 
88 template <typename T>
89 std::mutex ObjectRefMap<T>::allObjLock;
90 
91 template <typename T>
92 std::map<T *, uint32_t> ObjectRefMap<T>::refMap;
93 
94 template <typename T>
Insert(T * obj)95 void ObjectRefMap<T>::Insert(T *obj)
96 {
97     std::lock_guard<std::mutex> lock(allObjLock);
98     refMap[obj] = 1;
99 }
100 
101 template <typename T>
Erase(T * obj)102 void ObjectRefMap<T>::Erase(T *obj)
103 {
104     std::lock_guard<std::mutex> lock(allObjLock);
105     auto it = refMap.find(obj);
106     if (it != refMap.end()) {
107         refMap.erase(it);
108     }
109 }
110 
111 template <typename T>
IncreaseRef(T * obj)112 T *ObjectRefMap<T>::IncreaseRef(T *obj)
113 {
114     std::lock_guard<std::mutex> lock(allObjLock);
115     if (refMap.count(obj)) {
116         refMap[obj]++;
117         return obj;
118     } else {
119         return nullptr;
120     }
121 }
122 
123 template <typename T>
DecreaseRef(T * obj)124 void ObjectRefMap<T>::DecreaseRef(T *obj)
125 {
126     std::lock_guard<std::mutex> lock(allObjLock);
127     if (refMap.count(obj) && --refMap[obj] == 0) {
128         refMap.erase(obj);
129         delete obj;
130         obj = nullptr;
131     }
132 }
133 
134 template <typename T>
ObjectRefMap(T * obj)135 ObjectRefMap<T>::ObjectRefMap(T *obj)
136 {
137     if (obj != nullptr) {
138         obj_ = ObjectRefMap::IncreaseRef(obj);
139     }
140 }
141 
142 template <typename T>
~ObjectRefMap()143 ObjectRefMap<T>::~ObjectRefMap()
144 {
145     if (obj_ != nullptr) {
146         ObjectRefMap::DecreaseRef(obj_);
147     }
148 }
149 
150 template <typename T>
GetPtr()151 T *ObjectRefMap<T>::GetPtr()
152 {
153     return obj_;
154 }
155 
156 #define DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar)           \
157     do {                                                               \
158         void *data;                                                    \
159         napi_get_cb_info(env, info, &(argc), argv, &(thisVar), &data); \
160     } while (0)
161 
162 #define DRM_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar)             \
163     do {                                                                           \
164         void *data;                                                                \
165         status = napi_get_cb_info(env, info, nullptr, nullptr, &(thisVar), &data); \
166     } while (0)
167 
168 #define DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(cond, fmt, ...) \
169     do {                                              \
170         if (!(cond)) {                                \
171             DRM_ERR_LOG(fmt, ##__VA_ARGS__);          \
172             return;                                   \
173         }                                             \
174     } while (0)
175 
176 #define DRM_NAPI_CHECK_AND_CLOSE_RETURN_VOID_LOG(cond, fmt, ...) \
177     do {                                              \
178         if (!(cond)) {                                \
179             DRM_ERR_LOG(fmt, ##__VA_ARGS__);          \
180             napi_close_handle_scope(env, scope);      \
181             return;                                   \
182         }                                             \
183     } while (0)
184 
185 #define DRM_NAPI_CHECK_AND_RETURN_LOG(cond, status, fmt, ...) \
186     do {                                              \
187         if (!(cond)) {                                \
188             DRM_ERR_LOG(fmt, ##__VA_ARGS__);          \
189             return status;                                   \
190         }                                             \
191     } while (0)
192 
193 
194 /* check condition related to argc/argv, return and logging. */
195 #define NAPI_CHECK_ARGS_RETURN_VOID(context, condition, message, code)               \
196     do {                                                               \
197         if (!(condition)) {                                            \
198             (context)->status = napi_invalid_arg;                         \
199             (context)->errMessage = std::string(message);                      \
200             (context)->errCode = code;                      \
201             DRM_ERR_LOG("test (" #condition ") failed: " message);           \
202             return;                                                    \
203         }                                                              \
204     } while (0)
205 
206 #define NAPI_CHECK_STATUS_RETURN_VOID(context, message, code)                        \
207     do {                                                               \
208         if ((context)->status != napi_ok) {                               \
209             (context)->errMessage = std::string(message);                      \
210             (context)->errCode = code;                      \
211             DRM_ERR_LOG("test (context->status == napi_ok) failed: " message);  \
212             return;                                                    \
213         }                                                              \
214     } while (0)
215 
216 class NapiParamUtils {
217 public:
218     static napi_status GetValueInt32(const napi_env &env, int32_t &value, napi_value in);
219     static napi_status SetValueInt32(const napi_env &env, const int32_t &value, napi_value &result);
220     static napi_status GetValueInt32(const napi_env &env, const std::string &fieldStr, int32_t &value, napi_value in);
221     static napi_status SetValueInt32(const napi_env &env, const std::string &fieldStr,
222         const int32_t value, napi_value &result);
223 
224     static std::string GetStringArgument(napi_env env, napi_value value);
225     static napi_status SetValueString(const napi_env &env, const std::string &stringValue, napi_value &result);
226     static napi_status SetValueString(const napi_env &env, const std::string &fieldStr, const std::string &stringValue,
227         napi_value &result);
228 
229     static napi_value GetUndefinedValue(napi_env env);
230 
231     static napi_status SetValueUint8Array(const napi_env &env, const std::vector<uint8_t> &value,
232         napi_value &result);
233     static napi_status SetValueUint8Array(const napi_env &env, const std::string &fieldStr,
234         const std::vector<uint8_t> &value, napi_value &result);
235     static napi_status GetValueUint8Array(const napi_env &env, std::vector<uint8_t> &value,
236         napi_value in);
237     static napi_status SetValueBoolean(const napi_env &env, const bool boolValue, napi_value &result);
238     static napi_status SetValueMap(const napi_env &env,
239     std::map<std::vector<uint8_t>, MediaKeySessionKeyStatus> statusTable, napi_value &result);
240 
241     static napi_status GetValueOptionsData(const napi_env &env, std::map<std::string, std::string> &valueMap,
242         napi_value in);
243     static napi_status SetProvisionRequest(const napi_env &env, const NapiProvisionRequest &provisionRequest,
244         napi_value &result);
245     static napi_status SetMediaKeyRequest(const napi_env &env,
246         const IMediaKeySessionService::MediaKeyRequest &mediaKeyRequest, napi_value &result);
247     static napi_status SetDrmEventInfo(const napi_env &env, DrmEventParame &eventParame,
248         napi_value &result);
249     static napi_status SetDrmKeysChangeEventInfo(const napi_env &env, DrmKeysChangeEventParame &eventParame,
250         napi_value &statusTable, napi_value &hasNewGoodLicense);
251 };
252 } // namespace DrmStandard
253 } // namespace OHOS
254 #endif // NAPI_PARAM_UTILS_H
255