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 #include "napi_common.h"
16 #include "accesstoken_log.h"
17 
18 namespace OHOS {
19 namespace Security {
20 namespace AccessToken {
21 namespace {
22 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PRIVACY, "CommonNapi"};
23 } // namespace
24 
IsCurrentThread(std::thread::id threadId)25 bool IsCurrentThread(std::thread::id threadId)
26 {
27     std::thread::id currentThread = std::this_thread::get_id();
28     if (threadId != currentThread) {
29         ACCESSTOKEN_LOG_ERROR(LABEL, "Napi_ref can not be compared,different threadId");
30         return false;
31     }
32     return true;
33 }
CompareCallbackRef(const napi_env env,napi_ref subscriberRef,napi_ref unsubscriberRef,std::thread::id threadId)34 bool CompareCallbackRef(const napi_env env, napi_ref subscriberRef, napi_ref unsubscriberRef, std::thread::id threadId)
35 {
36     if (!IsCurrentThread(threadId)) {
37         return false;
38     }
39     napi_value subscriberCallback;
40     NAPI_CALL_BASE(env,
41         napi_get_reference_value(env, subscriberRef, &subscriberCallback), false);
42     napi_value unsubscriberCallback;
43     NAPI_CALL_BASE(env,
44         napi_get_reference_value(env, unsubscriberRef, &unsubscriberCallback), false);
45     bool result = false;
46     NAPI_CALL_BASE(env,
47         napi_strict_equals(env, subscriberCallback, unsubscriberCallback, &result), false);
48     return result;
49 }
50 
CheckType(const napi_env & env,const napi_value & value,const napi_valuetype & type)51 bool CheckType(const napi_env& env, const napi_value& value, const napi_valuetype& type)
52 {
53     napi_valuetype valuetype = napi_undefined;
54     napi_typeof(env, value, &valuetype);
55     if (valuetype != type) {
56         ACCESSTOKEN_LOG_ERROR(LABEL, "Value type dismatch, [%{public}d]->[%{public}d]", valuetype, type);
57         return false;
58     }
59     return true;
60 }
61 
ParseBool(const napi_env & env,const napi_value & value,bool & result)62 bool ParseBool(const napi_env& env, const napi_value& value, bool& result)
63 {
64     if (!CheckType(env, value, napi_boolean)) {
65         return false;
66     }
67 
68     if (napi_get_value_bool(env, value, &result) != napi_ok) {
69         ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot get value bool");
70         return false;
71     }
72     return true;
73 }
74 
ParseInt32(const napi_env & env,const napi_value & value,int32_t & result)75 bool ParseInt32(const napi_env& env, const napi_value& value, int32_t& result)
76 {
77     if (!CheckType(env, value, napi_number)) {
78         return false;
79     }
80     if (napi_get_value_int32(env, value, &result) != napi_ok) {
81         ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot get value int32");
82         return false;
83     }
84     return true;
85 }
86 
ParseInt64(const napi_env & env,const napi_value & value,int64_t & result)87 bool ParseInt64(const napi_env& env, const napi_value& value, int64_t& result)
88 {
89     if (!CheckType(env, value, napi_number)) {
90         return false;
91     }
92     if (napi_get_value_int64(env, value, &result) != napi_ok) {
93         ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot get value int64");
94         return false;
95     }
96     return true;
97 }
98 
ParseUint32(const napi_env & env,const napi_value & value,uint32_t & result)99 bool ParseUint32(const napi_env& env, const napi_value& value, uint32_t& result)
100 {
101     if (!CheckType(env, value, napi_number)) {
102         return false;
103     }
104     if (napi_get_value_uint32(env, value, &result) != napi_ok) {
105         ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot get value uint32");
106         return false;
107     }
108     return true;
109 }
110 
ParseString(const napi_env & env,const napi_value & value,std::string & result)111 bool ParseString(const napi_env& env, const napi_value& value, std::string& result)
112 {
113     if (!CheckType(env, value, napi_string)) {
114         return false;
115     }
116     size_t size;
117     if (napi_get_value_string_utf8(env, value, nullptr, 0, &size) != napi_ok) {
118         ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot get string size");
119         return false;
120     }
121     result.reserve(size + 1);
122     result.resize(size);
123     if (napi_get_value_string_utf8(env, value, result.data(), size + 1, &size) != napi_ok) {
124         ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot get value string");
125         return false;
126     }
127     return true;
128 }
129 
ParseStringArray(const napi_env & env,const napi_value & value,std::vector<std::string> & result)130 bool ParseStringArray(const napi_env& env, const napi_value& value, std::vector<std::string>& result)
131 {
132     if (!IsArray(env, value)) {
133         return false;
134     }
135 
136     uint32_t length = 0;
137     napi_get_array_length(env, value, &length);
138 
139     ACCESSTOKEN_LOG_INFO(LABEL, "Array size is %{public}d", length);
140 
141     if (length == 0) {
142         ACCESSTOKEN_LOG_INFO(LABEL, "Array is empty");
143         return true;
144     }
145 
146     napi_value valueArray;
147     for (uint32_t i = 0; i < length; i++) {
148         napi_get_element(env, value, i, &valueArray);
149 
150         std::string str;
151         if (!ParseString(env, valueArray, str)) {
152             return false;
153         }
154         result.emplace_back(str);
155     }
156     return true;
157 }
158 
ParseAccessTokenIDArray(const napi_env & env,const napi_value & value,std::vector<AccessTokenID> & result)159 bool ParseAccessTokenIDArray(const napi_env& env, const napi_value& value, std::vector<AccessTokenID>& result)
160 {
161     uint32_t length = 0;
162     if (!IsArray(env, value)) {
163         return false;
164     }
165     napi_get_array_length(env, value, &length);
166     napi_value valueArray;
167     for (uint32_t i = 0; i < length; i++) {
168         napi_get_element(env, value, i, &valueArray);
169         uint32_t res;
170         if (!ParseUint32(env, valueArray, res)) {
171             return false;
172         }
173         result.emplace_back(res);
174     }
175     return true;
176 };
177 
IsArray(const napi_env & env,const napi_value & value)178 bool IsArray(const napi_env& env, const napi_value& value)
179 {
180     bool isArray = false;
181     napi_status ret = napi_is_array(env, value, &isArray);
182     if (ret != napi_ok) {
183         return false;
184     }
185     return isArray;
186 }
187 
IsUndefinedOrNull(const napi_env & env,const napi_value & value)188 bool IsUndefinedOrNull(const napi_env& env, const napi_value& value)
189 {
190     napi_valuetype valueType = napi_undefined;
191     napi_typeof(env, value, &valueType);
192     return (valueType == napi_undefined) || (valueType == napi_null) ;
193 }
194 
IsNeedParseProperty(const napi_env & env,const napi_value & value,const std::string & key,napi_value & property)195 bool IsNeedParseProperty(
196     const napi_env& env, const napi_value& value, const std::string& key, napi_value& property)
197 {
198     bool hasProp = false;
199     property = nullptr;
200     napi_has_named_property(env, value, key.c_str(), &hasProp);
201     if (hasProp) {
202         napi_get_named_property(env, value, key.c_str(), &property);
203         napi_valuetype valueType = napi_undefined;
204         napi_typeof(env, property, &valueType);
205         return (valueType != napi_undefined) && (valueType != napi_null);
206     }
207     return false;
208 }
209 
ParseCallback(const napi_env & env,const napi_value & value,napi_ref & result)210 bool ParseCallback(const napi_env& env, const napi_value& value, napi_ref& result)
211 {
212     if (!CheckType(env, value, napi_function)) {
213         return false;
214     }
215     if (napi_create_reference(env, value, 1, &result) != napi_ok) {
216         ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot get value callback");
217         return false;
218     }
219     return true;
220 }
221 }  // namespace AccessToken
222 }  // namespace Security
223 }  // namespace OHOS
224