1 /*
2 * Copyright (c) 2022-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 #include "permission_record_manager_napi.h"
16 #include <cinttypes>
17 #include <vector>
18 #include "privacy_kit.h"
19 #include "accesstoken_log.h"
20 #include "napi_context_common.h"
21 #include "napi_common.h"
22 #include "napi_error.h"
23 #include "napi/native_api.h"
24 #include "napi/native_node_api.h"
25 #include "privacy_error.h"
26
27 namespace OHOS {
28 namespace Security {
29 namespace AccessToken {
30 std::mutex g_lockForPermActiveChangeSubscribers;
31 std::vector<RegisterPermActiveChangeContext*> g_permActiveChangeSubscribers;
32 static constexpr size_t MAX_CALLBACK_SIZE = 200;
33 static constexpr int32_t ADD_PERMISSION_RECORD_MAX_PARAMS = 5;
34 static constexpr int32_t ADD_PERMISSION_RECORD_MIN_PARAMS = 4;
35 static constexpr int32_t GET_PERMISSION_RECORD_MAX_PARAMS = 2;
36 static constexpr int32_t ON_OFF_MAX_PARAMS = 3;
37 static constexpr int32_t START_STOP_MAX_PARAMS = 3;
38 static constexpr int32_t GET_PERMISSION_USED_TYPE_MAX_PARAMS = 2;
39 static constexpr int32_t GET_PERMISSION_USED_TYPE_ONE_PARAMS = 1;
40 static constexpr int32_t FIRST_PARAM = 0;
41 static constexpr int32_t SECOND_PARAM = 1;
42 static constexpr int32_t THIRD_PARAM = 2;
43 static constexpr int32_t FOURTH_PARAM = 3;
44 static constexpr int32_t FIFTH_PARAM = 4;
45
46 namespace {
47 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PRIVACY, "PermissionRecordManagerNapi"};
48 } // namespace
49
GetJsErrorCode(int32_t errCode)50 static int32_t GetJsErrorCode(int32_t errCode)
51 {
52 int32_t jsCode;
53 switch (errCode) {
54 case RET_SUCCESS:
55 jsCode = JS_OK;
56 break;
57 case ERR_PERMISSION_DENIED:
58 jsCode = JS_ERROR_PERMISSION_DENIED;
59 break;
60 case ERR_NOT_SYSTEM_APP:
61 jsCode = JS_ERROR_NOT_SYSTEM_APP;
62 break;
63 case ERR_PARAM_INVALID:
64 jsCode = JS_ERROR_PARAM_INVALID;
65 break;
66 case ERR_TOKENID_NOT_EXIST:
67 jsCode = JS_ERROR_TOKENID_NOT_EXIST;
68 break;
69 case ERR_PERMISSION_NOT_EXIST:
70 jsCode = JS_ERROR_PERMISSION_NOT_EXIST;
71 break;
72 case ERR_CALLBACK_ALREADY_EXIST:
73 case ERR_CALLBACK_NOT_EXIST:
74 case ERR_PERMISSION_ALREADY_START_USING:
75 case ERR_PERMISSION_NOT_START_USING:
76 jsCode = JS_ERROR_NOT_USE_TOGETHER;
77 break;
78 case ERR_CALLBACKS_EXCEED_LIMITATION:
79 jsCode = JS_ERROR_REGISTERS_EXCEED_LIMITATION;
80 break;
81 case ERR_IDENTITY_CHECK_FAILED:
82 jsCode = JS_ERROR_PERMISSION_OPERATION_NOT_ALLOWED;
83 break;
84 case ERR_SERVICE_ABNORMAL:
85 case ERROR_IPC_REQUEST_FAIL:
86 case ERR_READ_PARCEL_FAILED:
87 case ERR_WRITE_PARCEL_FAILED:
88 jsCode = JS_ERROR_SERVICE_NOT_RUNNING;
89 break;
90 case ERR_MALLOC_FAILED:
91 jsCode = JS_ERROR_OUT_OF_MEMORY;
92 break;
93 default:
94 jsCode = JS_ERROR_INNER;
95 break;
96 }
97 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetJsErrorCode nativeCode(%{public}d) jsCode(%{public}d).", errCode, jsCode);
98 return jsCode;
99 }
100
ParamResolveErrorThrow(const napi_env & env,const std::string & param,const std::string & type)101 static void ParamResolveErrorThrow(const napi_env& env, const std::string& param, const std::string& type)
102 {
103 std::string errMsg = GetParamErrorMsg(param, type);
104 NAPI_CALL_RETURN_VOID(env, napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, errMsg)));
105 }
106
ReturnPromiseResult(napi_env env,const RecordManagerAsyncContext & context,napi_value result)107 static void ReturnPromiseResult(napi_env env, const RecordManagerAsyncContext& context, napi_value result)
108 {
109 if (context.retCode != RET_SUCCESS) {
110 int32_t jsCode = GetJsErrorCode(context.retCode);
111 napi_value businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
112 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, context.deferred, businessError));
113 } else {
114 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, context.deferred, result));
115 }
116 }
117
ReturnCallbackResult(napi_env env,const RecordManagerAsyncContext & context,napi_value result)118 static void ReturnCallbackResult(napi_env env, const RecordManagerAsyncContext& context, napi_value result)
119 {
120 napi_value businessError = GetNapiNull(env);
121 if (context.retCode != RET_SUCCESS) {
122 int32_t jsCode = GetJsErrorCode(context.retCode);
123 businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
124 }
125 napi_value results[ASYNC_CALL_BACK_VALUES_NUM] = { businessError, result };
126
127 napi_value callback = nullptr;
128 napi_value thisValue = nullptr;
129 napi_value thatValue = nullptr;
130 NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &thisValue));
131 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, 0, &thatValue));
132 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, context.callbackRef, &callback));
133 NAPI_CALL_RETURN_VOID(env,
134 napi_call_function(env, thisValue, callback, ASYNC_CALL_BACK_VALUES_NUM, results, &thatValue));
135 }
136
ParseAddPermissionFifthParam(const napi_env env,const napi_value & value,RecordManagerAsyncContext & asyncContext)137 static bool ParseAddPermissionFifthParam(const napi_env env, const napi_value& value,
138 RecordManagerAsyncContext& asyncContext)
139 {
140 napi_valuetype typeValue = napi_undefined;
141 napi_typeof(env, value, &typeValue);
142
143 if (typeValue == napi_object) {
144 // options
145 napi_value property = nullptr;
146 uint32_t type = 0;
147 /* if AddPermissionUsedRecordOptions exsit valid property, asyncContext.type use input param
148 * if not, asyncContext.type use default NORMAL_TYPE
149 */
150 if (IsNeedParseProperty(env, value, "usedType", property)) {
151 if (!ParseUint32(env, property, type)) {
152 ParamResolveErrorThrow(env, "AddPermissionUsedRecordOptions:usedType", "number");
153 return false;
154 }
155
156 asyncContext.type = static_cast<PermissionUsedType>(type);
157 }
158 } else if (typeValue == napi_function) {
159 // callback
160 if (!IsUndefinedOrNull(env, value) && !ParseCallback(env, value, asyncContext.callbackRef)) {
161 ParamResolveErrorThrow(env, "callback", "AsyncCallback");
162 return false;
163 }
164 }
165
166 return true;
167 }
168
ParseAddPermissionRecord(const napi_env env,const napi_callback_info info,RecordManagerAsyncContext & asyncContext)169 static bool ParseAddPermissionRecord(
170 const napi_env env, const napi_callback_info info, RecordManagerAsyncContext& asyncContext)
171 {
172 size_t argc = ADD_PERMISSION_RECORD_MAX_PARAMS;
173 napi_value argv[ADD_PERMISSION_RECORD_MAX_PARAMS] = { nullptr };
174 napi_value thisVar = nullptr;
175 void* data = nullptr;
176
177 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data), false);
178 if (argc < ADD_PERMISSION_RECORD_MIN_PARAMS) {
179 NAPI_CALL_BASE(env,
180 napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
181 return false;
182 }
183
184 asyncContext.env = env;
185 // 0: the first parameter of argv
186 if (!ParseUint32(env, argv[FIRST_PARAM], asyncContext.tokenId)) {
187 ParamResolveErrorThrow(env, "tokenID", "number");
188 return false;
189 }
190
191 // 1: the second parameter of argv
192 if (!ParseString(env, argv[SECOND_PARAM], asyncContext.permissionName)) {
193 ParamResolveErrorThrow(env, "permissionName", "string");
194 return false;
195 }
196
197 // 2: the third parameter of argv
198 if (!ParseInt32(env, argv[THIRD_PARAM], asyncContext.successCount)) {
199 ParamResolveErrorThrow(env, "successCount", "number");
200 return false;
201 }
202
203 // 3: the fourth parameter of argv
204 if (!ParseInt32(env, argv[FOURTH_PARAM], asyncContext.failCount)) {
205 ParamResolveErrorThrow(env, "failCount", "number");
206 return false;
207 }
208
209 // 4: the fifth parameter of argv, may be napi_object or napi_function
210 if (argc == ADD_PERMISSION_RECORD_MAX_PARAMS) {
211 if (!ParseAddPermissionFifthParam(env, argv[FIFTH_PARAM], asyncContext)) {
212 return false;
213 }
214 }
215
216 return true;
217 }
218
ParseStartAndStopUsingPermission(const napi_env env,const napi_callback_info info,RecordManagerAsyncContext & asyncContext)219 static bool ParseStartAndStopUsingPermission(
220 const napi_env env, const napi_callback_info info, RecordManagerAsyncContext& asyncContext)
221 {
222 size_t argc = START_STOP_MAX_PARAMS;
223 napi_value argv[START_STOP_MAX_PARAMS] = { nullptr };
224 napi_value thisVar = nullptr;
225 void* data = nullptr;
226
227 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data), false);
228 if (argc < START_STOP_MAX_PARAMS - 1) {
229 NAPI_CALL_BASE(env,
230 napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
231 return false;
232 }
233
234 asyncContext.env = env;
235 // 0: the first parameter of argv
236 if (!ParseUint32(env, argv[0], asyncContext.tokenId)) {
237 ParamResolveErrorThrow(env, "tokenId", "number");
238 return false;
239 }
240
241 // 1: the second parameter of argv
242 if (!ParseString(env, argv[1], asyncContext.permissionName)) {
243 ParamResolveErrorThrow(env, "permissionName", "string");
244 return false;
245 }
246 if (argc == START_STOP_MAX_PARAMS) {
247 // 2: the third parameter of argv
248 if (!IsUndefinedOrNull(env, argv[2]) && !ParseCallback(env, argv[2], asyncContext.callbackRef)) {
249 ParamResolveErrorThrow(env, "callback", "AsyncCallback");
250 return false;
251 }
252 }
253 return true;
254 }
255
ConvertDetailUsedRecord(napi_env env,napi_value value,const UsedRecordDetail & detailRecord)256 static void ConvertDetailUsedRecord(napi_env env, napi_value value, const UsedRecordDetail& detailRecord)
257 {
258 napi_value nStatus;
259 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, detailRecord.status, &nStatus));
260 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "status", nStatus));
261
262 napi_value nLockScreenStatus;
263 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, detailRecord.lockScreenStatus, &nLockScreenStatus));
264 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "lockScreenStatus", nLockScreenStatus));
265
266 napi_value nTimestamp;
267 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, detailRecord.timestamp, &nTimestamp));
268 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "timestamp", nTimestamp));
269
270 napi_value nAccessDuration;
271 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, detailRecord.accessDuration, &nAccessDuration));
272 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "accessDuration", nAccessDuration));
273
274 napi_value nCount;
275 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, detailRecord.count, &nCount));
276 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "count", nCount));
277
278 napi_value nUsedType;
279 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, detailRecord.type, &nUsedType));
280 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "usedType", nUsedType));
281 }
282
ConvertPermissionUsedRecord(napi_env env,napi_value value,const PermissionUsedRecord & permissionRecord)283 static void ConvertPermissionUsedRecord(napi_env env, napi_value value, const PermissionUsedRecord& permissionRecord)
284 {
285 napi_value nPermissionName;
286 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env,
287 permissionRecord.permissionName.c_str(), NAPI_AUTO_LENGTH, &nPermissionName));
288 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "permissionName", nPermissionName));
289
290 napi_value nAccessCount;
291 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, permissionRecord.accessCount, &nAccessCount));
292 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "accessCount", nAccessCount));
293
294 napi_value nRejectCount;
295 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, permissionRecord.rejectCount, &nRejectCount));
296 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "rejectCount", nRejectCount));
297
298 napi_value nLastAccessTime;
299 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, permissionRecord.lastAccessTime, &nLastAccessTime));
300 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "lastAccessTime", nLastAccessTime));
301
302 napi_value nLastRejectTime;
303 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, permissionRecord.lastRejectTime, &nLastRejectTime));
304 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "lastRejectTime", nLastRejectTime));
305
306 napi_value nLastAccessDuration;
307 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, permissionRecord.lastAccessDuration, &nLastAccessDuration));
308 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "lastAccessDuration", nLastAccessDuration));
309
310 size_t index = 0;
311 napi_value objAccessRecords;
312 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &objAccessRecords));
313 for (const auto& accRecord : permissionRecord.accessRecords) {
314 napi_value objAccessRecord;
315 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objAccessRecord));
316 ConvertDetailUsedRecord(env, objAccessRecord, accRecord);
317 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objAccessRecords, index, objAccessRecord));
318 index++;
319 }
320 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "accessRecords", objAccessRecords));
321
322 index = 0;
323 napi_value objRejectRecords;
324 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &objRejectRecords));
325 for (const auto& rejRecord : permissionRecord.rejectRecords) {
326 napi_value objRejectRecord;
327 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objRejectRecord));
328 ConvertDetailUsedRecord(env, objRejectRecord, rejRecord);
329 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objRejectRecords, index, objRejectRecord));
330 index++;
331 }
332 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "rejectRecords", objRejectRecords));
333 }
334
ConvertBundleUsedRecord(napi_env env,napi_value value,const BundleUsedRecord & bundleRecord)335 static void ConvertBundleUsedRecord(napi_env env, napi_value value, const BundleUsedRecord& bundleRecord)
336 {
337 napi_value nTokenId;
338 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, bundleRecord.tokenId, &nTokenId));
339 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "tokenId", nTokenId));
340
341 napi_value nIsRemote;
342 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, bundleRecord.isRemote, &nIsRemote));
343 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "isRemote", nIsRemote));
344
345 napi_value nDeviceId;
346 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env,
347 bundleRecord.deviceId.c_str(), NAPI_AUTO_LENGTH, &nDeviceId));
348 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "deviceId", nDeviceId));
349
350 napi_value nBundleName;
351 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env,
352 bundleRecord.bundleName.c_str(), NAPI_AUTO_LENGTH, &nBundleName));
353 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "bundleName", nBundleName));
354 size_t index = 0;
355 napi_value objPermissionRecords;
356 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &objPermissionRecords));
357 for (const auto& permRecord : bundleRecord.permissionRecords) {
358 napi_value objPermissionRecord;
359 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objPermissionRecord));
360 ConvertPermissionUsedRecord(env, objPermissionRecord, permRecord);
361 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objPermissionRecords, index, objPermissionRecord));
362 index++;
363 }
364 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "permissionRecords", objPermissionRecords));
365 }
366
ProcessRecordResult(napi_env env,napi_value value,const PermissionUsedResult & result)367 static void ProcessRecordResult(napi_env env, napi_value value, const PermissionUsedResult& result)
368 {
369 napi_value nBeginTimestamp;
370 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, result.beginTimeMillis, &nBeginTimestamp));
371 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "beginTime", nBeginTimestamp));
372
373 napi_value nEndTimestamp;
374 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, result.endTimeMillis, &nEndTimestamp));
375 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "endTime", nEndTimestamp));
376
377 size_t index = 0;
378 napi_value objBundleRecords;
379 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &objBundleRecords));
380 for (const auto& bundleRecord : result.bundleRecords) {
381 napi_value objBundleRecord;
382 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objBundleRecord));
383 ConvertBundleUsedRecord(env, objBundleRecord, bundleRecord);
384 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objBundleRecords, index, objBundleRecord));
385 index++;
386 }
387 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "bundleRecords", objBundleRecords));
388 }
389
ParseRequest(const napi_env & env,const napi_value & value,PermissionUsedRequest & request)390 static bool ParseRequest(const napi_env& env, const napi_value& value, PermissionUsedRequest& request)
391 {
392 napi_value property = nullptr;
393 if (IsNeedParseProperty(env, value, "tokenId", property) && !ParseUint32(env, property, request.tokenId)) {
394 ParamResolveErrorThrow(env, "request:tokenId", "number");
395 return false;
396 }
397
398 if (IsNeedParseProperty(env, value, "isRemote", property) && !ParseBool(env, property, request.isRemote)) {
399 ParamResolveErrorThrow(env, "request:isRemote", "boolean");
400 return false;
401 }
402
403 if (IsNeedParseProperty(env, value, "deviceId", property) && !ParseString(env, property, request.deviceId)) {
404 ParamResolveErrorThrow(env, "request:deviceId", "string");
405 return false;
406 }
407
408 if (IsNeedParseProperty(env, value, "bundleName", property) && !ParseString(env, property, request.bundleName)) {
409 ParamResolveErrorThrow(env, "request:bundleName", "string");
410 return false;
411 }
412
413 if (IsNeedParseProperty(env, value, "beginTime", property) && !ParseInt64(env, property, request.beginTimeMillis)) {
414 ParamResolveErrorThrow(env, "request:beginTime", "number");
415 return false;
416 }
417
418 if (IsNeedParseProperty(env, value, "endTime", property) && !ParseInt64(env, property, request.endTimeMillis)) {
419 ParamResolveErrorThrow(env, "request:endTime", "number");
420 return false;
421 }
422
423 if (IsNeedParseProperty(env, value, "permissionNames", property) &&
424 !ParseStringArray(env, property, request.permissionList)) {
425 ParamResolveErrorThrow(env, "request:permissionNames", "Array<string>");
426 return false;
427 }
428
429 property = nullptr;
430 NAPI_CALL_BASE(env, napi_get_named_property(env, value, "flag", &property), false);
431 int32_t flag;
432 if (!ParseInt32(env, property, flag)) {
433 ParamResolveErrorThrow(env, "request:flag", "number");
434 return false;
435 }
436 request.flag = static_cast<PermissionUsageFlagEnum>(flag);
437 return true;
438 }
439
ParseGetPermissionUsedRecords(const napi_env env,const napi_callback_info info,RecordManagerAsyncContext & asyncContext)440 static bool ParseGetPermissionUsedRecords(
441 const napi_env env, const napi_callback_info info, RecordManagerAsyncContext& asyncContext)
442 {
443 size_t argc = GET_PERMISSION_RECORD_MAX_PARAMS;
444 napi_value argv[GET_PERMISSION_RECORD_MAX_PARAMS] = { nullptr };
445 napi_value thisVar = nullptr;
446 void* data = nullptr;
447 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data), false);
448 if (argc < GET_PERMISSION_RECORD_MAX_PARAMS - 1) {
449 NAPI_CALL_BASE(env,
450 napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
451 return false;
452 }
453
454 asyncContext.env = env;
455
456 // 0: the first parameter of argv
457 if (!CheckType(env, argv[0], napi_object)) {
458 ParamResolveErrorThrow(env, "request", "PermissionUsedRequest");
459 return false;
460 }
461 if (!ParseRequest(env, argv[0], asyncContext.request)) {
462 return false;
463 }
464
465 if (argc == GET_PERMISSION_RECORD_MAX_PARAMS) {
466 // 1: the second parameter of argv
467 if (!IsUndefinedOrNull(env, argv[1]) && !ParseCallback(env, argv[1], asyncContext.callbackRef)) {
468 ParamResolveErrorThrow(env, "callback", "AsyncCallback");
469 return false;
470 }
471 }
472 return true;
473 }
474
AddPermissionUsedRecordExecute(napi_env env,void * data)475 static void AddPermissionUsedRecordExecute(napi_env env, void* data)
476 {
477 ACCESSTOKEN_LOG_DEBUG(LABEL, "AddPermissionUsedRecord execute.");
478 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
479 if (asyncContext == nullptr) {
480 return;
481 }
482
483 AddPermParamInfo info;
484 info.tokenId = asyncContext->tokenId;
485 info.permissionName = asyncContext->permissionName;
486 info.successCount = asyncContext->successCount;
487 info.failCount = asyncContext->failCount;
488 info.type = asyncContext->type;
489 asyncContext->retCode = PrivacyKit::AddPermissionUsedRecord(info);
490 }
491
AddPermissionUsedRecordComplete(napi_env env,napi_status status,void * data)492 static void AddPermissionUsedRecordComplete(napi_env env, napi_status status, void* data)
493 {
494 ACCESSTOKEN_LOG_DEBUG(LABEL, "AddPermissionUsedRecord complete.");
495 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
496 std::unique_ptr<RecordManagerAsyncContext> callbackPtr {asyncContext};
497
498 napi_value result = GetNapiNull(env);
499 if (asyncContext->deferred != nullptr) {
500 ReturnPromiseResult(env, *asyncContext, result);
501 } else {
502 ReturnCallbackResult(env, *asyncContext, result);
503 }
504 }
505
AddPermissionUsedRecord(napi_env env,napi_callback_info cbinfo)506 napi_value AddPermissionUsedRecord(napi_env env, napi_callback_info cbinfo)
507 {
508 ACCESSTOKEN_LOG_DEBUG(LABEL, "AddPermissionUsedRecord begin.");
509
510 auto *asyncContext = new (std::nothrow) RecordManagerAsyncContext(env);
511 if (asyncContext == nullptr) {
512 ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
513 return nullptr;
514 }
515
516 std::unique_ptr<RecordManagerAsyncContext> callbackPtr {asyncContext};
517 if (!ParseAddPermissionRecord(env, cbinfo, *asyncContext)) {
518 return nullptr;
519 }
520
521 napi_value result = nullptr;
522 if (asyncContext->callbackRef == nullptr) {
523 NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
524 } else {
525 NAPI_CALL(env, napi_get_undefined(env, &result));
526 }
527
528 napi_value resource = nullptr;
529 NAPI_CALL(env, napi_create_string_utf8(env, "AddPermissionUsedRecord", NAPI_AUTO_LENGTH, &resource));
530
531 NAPI_CALL(env, napi_create_async_work(env,
532 nullptr,
533 resource,
534 AddPermissionUsedRecordExecute,
535 AddPermissionUsedRecordComplete,
536 reinterpret_cast<void *>(asyncContext),
537 &(asyncContext->asyncWork)));
538 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->asyncWork, napi_qos_default));
539 callbackPtr.release();
540 return result;
541 }
542
StartUsingPermissionExecute(napi_env env,void * data)543 static void StartUsingPermissionExecute(napi_env env, void* data)
544 {
545 ACCESSTOKEN_LOG_DEBUG(LABEL, "StartUsingPermission execute.");
546 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
547 if (asyncContext == nullptr) {
548 return;
549 }
550
551 asyncContext->retCode = PrivacyKit::StartUsingPermission(asyncContext->tokenId,
552 asyncContext->permissionName);
553 }
554
StartUsingPermissionComplete(napi_env env,napi_status status,void * data)555 static void StartUsingPermissionComplete(napi_env env, napi_status status, void* data)
556 {
557 ACCESSTOKEN_LOG_DEBUG(LABEL, "StartUsingPermission complete.");
558 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
559 std::unique_ptr<RecordManagerAsyncContext> callbackPtr{asyncContext};
560
561 napi_value result = GetNapiNull(env);
562 if (asyncContext->deferred != nullptr) {
563 ReturnPromiseResult(env, *asyncContext, result);
564 } else {
565 ReturnCallbackResult(env, *asyncContext, result);
566 }
567 }
568
StartUsingPermission(napi_env env,napi_callback_info cbinfo)569 napi_value StartUsingPermission(napi_env env, napi_callback_info cbinfo)
570 {
571 ACCESSTOKEN_LOG_DEBUG(LABEL, "StartUsingPermission begin.");
572 auto *asyncContext = new (std::nothrow) RecordManagerAsyncContext(env);
573 if (asyncContext == nullptr) {
574 ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
575 return nullptr;
576 }
577
578 std::unique_ptr<RecordManagerAsyncContext> callbackPtr {asyncContext};
579 if (!ParseStartAndStopUsingPermission(env, cbinfo, *asyncContext)) {
580 return nullptr;
581 }
582
583 napi_value result = nullptr;
584 if (asyncContext->callbackRef == nullptr) {
585 NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
586 } else {
587 NAPI_CALL(env, napi_get_undefined(env, &result));
588 }
589
590 napi_value resource = nullptr;
591 NAPI_CALL(env, napi_create_string_utf8(env, "StartUsingPermission", NAPI_AUTO_LENGTH, &resource));
592
593 NAPI_CALL(env, napi_create_async_work(env,
594 nullptr,
595 resource,
596 StartUsingPermissionExecute,
597 StartUsingPermissionComplete,
598 reinterpret_cast<void *>(asyncContext),
599 &(asyncContext->asyncWork)));
600 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->asyncWork, napi_qos_default));
601 callbackPtr.release();
602 return result;
603 }
604
StopUsingPermissionExecute(napi_env env,void * data)605 static void StopUsingPermissionExecute(napi_env env, void* data)
606 {
607 ACCESSTOKEN_LOG_DEBUG(LABEL, "StopUsingPermission execute.");
608 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
609 if (asyncContext == nullptr) {
610 return;
611 }
612
613 asyncContext->retCode = PrivacyKit::StopUsingPermission(asyncContext->tokenId,
614 asyncContext->permissionName);
615 }
616
StopUsingPermissionComplete(napi_env env,napi_status status,void * data)617 static void StopUsingPermissionComplete(napi_env env, napi_status status, void* data)
618 {
619 ACCESSTOKEN_LOG_DEBUG(LABEL, "StopUsingPermission complete.");
620 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
621 std::unique_ptr<RecordManagerAsyncContext> callbackPtr{asyncContext};
622
623 napi_value result = GetNapiNull(env);
624 if (asyncContext->deferred != nullptr) {
625 ReturnPromiseResult(env, *asyncContext, result);
626 } else {
627 ReturnCallbackResult(env, *asyncContext, result);
628 }
629 }
630
StopUsingPermission(napi_env env,napi_callback_info cbinfo)631 napi_value StopUsingPermission(napi_env env, napi_callback_info cbinfo)
632 {
633 ACCESSTOKEN_LOG_DEBUG(LABEL, "StopUsingPermission begin.");
634
635 auto *asyncContext = new (std::nothrow) RecordManagerAsyncContext(env);
636 if (asyncContext == nullptr) {
637 ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
638 return nullptr;
639 }
640
641 std::unique_ptr<RecordManagerAsyncContext> callbackPtr {asyncContext};
642 if (!ParseStartAndStopUsingPermission(env, cbinfo, *asyncContext)) {
643 return nullptr;
644 }
645
646 napi_value result = nullptr;
647 if (asyncContext->callbackRef == nullptr) {
648 NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
649 } else {
650 NAPI_CALL(env, napi_get_undefined(env, &result));
651 }
652
653 napi_value resource = nullptr;
654 NAPI_CALL(env, napi_create_string_utf8(env, "StopUsingPermission", NAPI_AUTO_LENGTH, &resource));
655
656 NAPI_CALL(env, napi_create_async_work(env,
657 nullptr,
658 resource,
659 StopUsingPermissionExecute,
660 StopUsingPermissionComplete,
661 reinterpret_cast<void *>(asyncContext),
662 &(asyncContext->asyncWork)));
663 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->asyncWork, napi_qos_default));
664 callbackPtr.release();
665 return result;
666 }
667
GetPermissionUsedRecordsExecute(napi_env env,void * data)668 static void GetPermissionUsedRecordsExecute(napi_env env, void* data)
669 {
670 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionUsedRecords execute.");
671 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
672 if (asyncContext == nullptr) {
673 return;
674 }
675
676 asyncContext->retCode = PrivacyKit::GetPermissionUsedRecords(asyncContext->request, asyncContext->result);
677 }
678
GetPermissionUsedRecordsComplete(napi_env env,napi_status status,void * data)679 static void GetPermissionUsedRecordsComplete(napi_env env, napi_status status, void* data)
680 {
681 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionUsedRecords complete.");
682 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
683 std::unique_ptr<RecordManagerAsyncContext> callbackPtr{asyncContext};
684
685 napi_value result = GetNapiNull(env);
686 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result));
687 ProcessRecordResult(env, result, asyncContext->result);
688 if (asyncContext->deferred != nullptr) {
689 ReturnPromiseResult(env, *asyncContext, result);
690 } else {
691 ReturnCallbackResult(env, *asyncContext, result);
692 }
693 }
694
GetPermissionUsedRecords(napi_env env,napi_callback_info cbinfo)695 napi_value GetPermissionUsedRecords(napi_env env, napi_callback_info cbinfo)
696 {
697 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionUsedRecords begin.");
698 auto *asyncContext = new (std::nothrow) RecordManagerAsyncContext(env);
699 if (asyncContext == nullptr) {
700 ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
701 return nullptr;
702 }
703
704 std::unique_ptr<RecordManagerAsyncContext> callbackPtr {asyncContext};
705 if (!ParseGetPermissionUsedRecords(env, cbinfo, *asyncContext)) {
706 return nullptr;
707 }
708
709 napi_value result = nullptr;
710 if (asyncContext->callbackRef == nullptr) {
711 NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
712 } else {
713 NAPI_CALL(env, napi_get_undefined(env, &result));
714 }
715
716 napi_value resource = nullptr;
717 NAPI_CALL(env, napi_create_string_utf8(env, "GetPermissionUsedRecords", NAPI_AUTO_LENGTH, &resource));
718
719 NAPI_CALL(env, napi_create_async_work(env,
720 nullptr,
721 resource,
722 GetPermissionUsedRecordsExecute,
723 GetPermissionUsedRecordsComplete,
724 reinterpret_cast<void *>(asyncContext),
725 &(asyncContext->asyncWork)));
726 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->asyncWork, napi_qos_default));
727 callbackPtr.release();
728 return result;
729 }
730
ParseInputToRegister(const napi_env env,const napi_callback_info cbInfo,RegisterPermActiveChangeContext & registerPermActiveChangeContext)731 static bool ParseInputToRegister(const napi_env env, const napi_callback_info cbInfo,
732 RegisterPermActiveChangeContext& registerPermActiveChangeContext)
733 {
734 size_t argc = ON_OFF_MAX_PARAMS;
735 napi_value argv[ON_OFF_MAX_PARAMS] = {nullptr};
736 napi_value thisVar = nullptr;
737 napi_ref callback = nullptr;
738 NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr), false);
739 if (argc < ON_OFF_MAX_PARAMS) {
740 NAPI_CALL_BASE(
741 env, napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
742 return false;
743 }
744
745 std::string type;
746 // 0: the first parameter of argv
747 if (!ParseString(env, argv[0], type)) {
748 ParamResolveErrorThrow(env, "type", "string");
749 return false;
750 }
751 std::vector<std::string> permList;
752 // 1: the second parameter of argv
753 if (!ParseStringArray(env, argv[1], permList)) {
754 ParamResolveErrorThrow(env, "permList", "Array<string>");
755 return false;
756 }
757 std::sort(permList.begin(), permList.end());
758 // 2: the third parameter of argv
759 if (!ParseCallback(env, argv[2], callback)) {
760 ParamResolveErrorThrow(env, "callback", "AsyncCallback");
761 return false;
762 }
763 registerPermActiveChangeContext.env = env;
764 registerPermActiveChangeContext.callbackRef = callback;
765 registerPermActiveChangeContext.type = type;
766 registerPermActiveChangeContext.subscriber = std::make_shared<PermActiveStatusPtr>(permList);
767 registerPermActiveChangeContext.subscriber->SetEnv(env);
768 registerPermActiveChangeContext.subscriber->SetCallbackRef(callback);
769 registerPermActiveChangeContext.threadId_ = std::this_thread::get_id();
770 return true;
771 }
772
ParseInputToUnregister(const napi_env env,const napi_callback_info cbInfo,UnregisterPermActiveChangeContext & unregisterPermActiveChangeContext)773 static bool ParseInputToUnregister(const napi_env env, const napi_callback_info cbInfo,
774 UnregisterPermActiveChangeContext& unregisterPermActiveChangeContext)
775 {
776 size_t argc = ON_OFF_MAX_PARAMS;
777 napi_value argv[ON_OFF_MAX_PARAMS] = {nullptr};
778 napi_value thisVar = nullptr;
779 napi_ref callback = nullptr;
780 NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr), false);
781 if (argc < ON_OFF_MAX_PARAMS - 1) {
782 NAPI_CALL_BASE(
783 env, napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
784 return false;
785 }
786
787 std::string type;
788 // 0: the first parameter of argv
789 if (!ParseString(env, argv[0], type)) {
790 ParamResolveErrorThrow(env, "permList", "Array<string>");
791 return false;
792 }
793 // 1: the second parameter of argv
794 std::vector<std::string> permList;
795 if (!ParseStringArray(env, argv[1], permList)) {
796 ParamResolveErrorThrow(env, "permList", "Array<string>");
797 return false;
798 }
799 std::sort(permList.begin(), permList.end());
800 if (argc == ON_OFF_MAX_PARAMS) {
801 // 2: the first parameter of argv
802 if (!ParseCallback(env, argv[2], callback)) {
803 ParamResolveErrorThrow(env, "callback", "AsyncCallback");
804 return false;
805 }
806 }
807 unregisterPermActiveChangeContext.env = env;
808 unregisterPermActiveChangeContext.callbackRef = callback;
809 unregisterPermActiveChangeContext.type = type;
810 unregisterPermActiveChangeContext.permList = permList;
811 unregisterPermActiveChangeContext.threadId_ = std::this_thread::get_id();
812 return true;
813 }
814
IsExistRegister(const PermActiveChangeContext * permActiveChangeContext)815 static bool IsExistRegister(const PermActiveChangeContext* permActiveChangeContext)
816 {
817 std::vector<std::string> targetPermList;
818 permActiveChangeContext->subscriber->GetPermList(targetPermList);
819 std::lock_guard<std::mutex> lock(g_lockForPermActiveChangeSubscribers);
820 for (const auto& item : g_permActiveChangeSubscribers) {
821 std::vector<std::string> permList;
822 item->subscriber->GetPermList(permList);
823 bool hasPermIntersection = false;
824 // Special cases:
825 // 1.Have registered full, and then register some
826 // 2.Have registered some, then register full
827 if (permList.empty() || targetPermList.empty()) {
828 hasPermIntersection = true;
829 }
830 for (const auto& PermItem : targetPermList) {
831 if (hasPermIntersection) {
832 break;
833 }
834 auto iter = std::find(permList.begin(), permList.end(), PermItem);
835 if (iter != permList.end()) {
836 hasPermIntersection = true;
837 }
838 }
839 if (hasPermIntersection && CompareCallbackRef(permActiveChangeContext->env,
840 item->callbackRef, permActiveChangeContext->callbackRef, item->threadId_)) {
841 return true;
842 }
843 }
844 return false;
845 }
846
DeleteRegisterInVector(PermActiveChangeContext * permActiveChangeContext)847 static void DeleteRegisterInVector(PermActiveChangeContext* permActiveChangeContext)
848 {
849 std::vector<std::string> targetPermList;
850 permActiveChangeContext->subscriber->GetPermList(targetPermList);
851 std::lock_guard<std::mutex> lock(g_lockForPermActiveChangeSubscribers);
852 auto item = g_permActiveChangeSubscribers.begin();
853 while (item != g_permActiveChangeSubscribers.end()) {
854 std::vector<std::string> permList;
855 (*item)->subscriber->GetPermList(permList);
856 if ((permList == targetPermList) && CompareCallbackRef(permActiveChangeContext->env, (*item)->callbackRef,
857 permActiveChangeContext->callbackRef, (*item)->threadId_)) {
858 delete *item;
859 *item = nullptr;
860 g_permActiveChangeSubscribers.erase(item);
861 return;
862 } else {
863 ++item;
864 }
865 }
866 }
867
FindAndGetSubscriber(UnregisterPermActiveChangeContext * unregisterPermActiveChangeContext,std::vector<RegisterPermActiveChangeContext * > & batchPermActiveChangeSubscribers)868 static bool FindAndGetSubscriber(UnregisterPermActiveChangeContext* unregisterPermActiveChangeContext,
869 std::vector<RegisterPermActiveChangeContext*>& batchPermActiveChangeSubscribers)
870 {
871 std::vector<std::string> targetPermList = unregisterPermActiveChangeContext->permList;
872 std::lock_guard<std::mutex> lock(g_lockForPermActiveChangeSubscribers);
873 bool callbackEqual;
874 napi_ref callbackRef = unregisterPermActiveChangeContext->callbackRef;
875 for (const auto& item : g_permActiveChangeSubscribers) {
876 std::vector<std::string> permList;
877 item->subscriber->GetPermList(permList);
878 // targetCallback == nullptr, Unsubscribe from all callbacks under the same permList
879 // targetCallback != nullptr, unregister the subscriber with same permList and callback
880 if (callbackRef == nullptr) {
881 // batch delete currentThread callback
882 callbackEqual = IsCurrentThread(item->threadId_);
883 } else {
884 callbackEqual = CompareCallbackRef(
885 unregisterPermActiveChangeContext->env, item->callbackRef, callbackRef, item->threadId_);
886 }
887
888 if ((permList == targetPermList) && callbackEqual) {
889 batchPermActiveChangeSubscribers.emplace_back(item);
890 if (callbackRef != nullptr) {
891 return true;
892 }
893 }
894 }
895 if (!batchPermActiveChangeSubscribers.empty()) {
896 return true;
897 }
898 return false;
899 }
900
RegisterPermActiveChangeCallback(napi_env env,napi_callback_info cbInfo)901 napi_value RegisterPermActiveChangeCallback(napi_env env, napi_callback_info cbInfo)
902 {
903 RegisterPermActiveChangeContext* registerPermActiveChangeContext =
904 new (std::nothrow) RegisterPermActiveChangeContext();
905 if (registerPermActiveChangeContext == nullptr) {
906 ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for registerPermActiveChangeContext!");
907 return nullptr;
908 }
909 std::unique_ptr<RegisterPermActiveChangeContext> callbackPtr {registerPermActiveChangeContext};
910 if (!ParseInputToRegister(env, cbInfo, *registerPermActiveChangeContext)) {
911 return nullptr;
912 }
913 if (IsExistRegister(registerPermActiveChangeContext)) {
914 ACCESSTOKEN_LOG_ERROR(LABEL, "Subscribe failed. The current subscriber has been existed");
915 std::string errMsg = GetErrorMessage(JsErrorCode::JS_ERROR_PARAM_INVALID);
916 NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_INVALID, errMsg)));
917 return nullptr;
918 }
919 int32_t result = PrivacyKit::RegisterPermActiveStatusCallback(registerPermActiveChangeContext->subscriber);
920 if (result != RET_SUCCESS) {
921 ACCESSTOKEN_LOG_ERROR(LABEL, "RegisterPermActiveStatusCallback failed");
922 int32_t jsCode = GetJsErrorCode(result);
923 std::string errMsg = GetErrorMessage(jsCode);
924 NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, jsCode, errMsg)));
925 return nullptr;
926 }
927 {
928 std::lock_guard<std::mutex> lock(g_lockForPermActiveChangeSubscribers);
929 if (g_permActiveChangeSubscribers.size() >= MAX_CALLBACK_SIZE) {
930 ACCESSTOKEN_LOG_ERROR(LABEL, "Subscribers size has reached max value");
931 return nullptr;
932 }
933 g_permActiveChangeSubscribers.emplace_back(registerPermActiveChangeContext);
934 }
935 callbackPtr.release();
936 return nullptr;
937 }
938
UnregisterPermActiveChangeCallback(napi_env env,napi_callback_info cbInfo)939 napi_value UnregisterPermActiveChangeCallback(napi_env env, napi_callback_info cbInfo)
940 {
941 UnregisterPermActiveChangeContext* unregisterPermActiveChangeContext =
942 new (std::nothrow) UnregisterPermActiveChangeContext();
943 if (unregisterPermActiveChangeContext == nullptr) {
944 ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for unregisterPermActiveChangeContext!");
945 return nullptr;
946 }
947 std::unique_ptr<UnregisterPermActiveChangeContext> callbackPtr {unregisterPermActiveChangeContext};
948 if (!ParseInputToUnregister(env, cbInfo, *unregisterPermActiveChangeContext)) {
949 return nullptr;
950 }
951 std::vector<RegisterPermActiveChangeContext*> batchPermActiveChangeSubscribers;
952 if (!FindAndGetSubscriber(unregisterPermActiveChangeContext, batchPermActiveChangeSubscribers)) {
953 ACCESSTOKEN_LOG_ERROR(LABEL, "Unsubscribe failed. The current subscriber does not exist");
954 std::string errMsg = GetErrorMessage(JsErrorCode::JS_ERROR_PARAM_INVALID);
955 NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_INVALID, errMsg)));
956 return nullptr;
957 }
958 for (const auto& item : batchPermActiveChangeSubscribers) {
959 int32_t result = PrivacyKit::UnRegisterPermActiveStatusCallback(item->subscriber);
960 if (result == RET_SUCCESS) {
961 DeleteRegisterInVector(item);
962 } else {
963 ACCESSTOKEN_LOG_ERROR(LABEL, "UnregisterPermActiveChangeCompleted failed");
964 int32_t jsCode = GetJsErrorCode(result);
965 std::string errMsg = GetErrorMessage(jsCode);
966 NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, jsCode, errMsg)));
967 }
968 }
969 return nullptr;
970 }
971
ParseGetPermissionUsedType(const napi_env env,const napi_callback_info cbInfo,PermissionUsedTypeAsyncContext & context)972 static bool ParseGetPermissionUsedType(const napi_env env, const napi_callback_info cbInfo,
973 PermissionUsedTypeAsyncContext& context)
974 {
975 size_t argc = GET_PERMISSION_USED_TYPE_MAX_PARAMS;
976 napi_value argv[GET_PERMISSION_USED_TYPE_MAX_PARAMS] = {nullptr};
977 napi_value thisVar = nullptr;
978 NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr), false);
979
980 AccessTokenID tokenId = 0;
981 std::string permissionName;
982
983 if (argc == GET_PERMISSION_USED_TYPE_ONE_PARAMS) {
984 // one param: only tokenId
985 if (!ParseUint32(env, argv[0], tokenId)) {
986 ParamResolveErrorThrow(env, "tokenId", "number");
987 return false;
988 }
989 } else if (argc == GET_PERMISSION_USED_TYPE_MAX_PARAMS) {
990 // two params: tokenId + permissionName or null + permissionName
991 if (!IsUndefinedOrNull(env, argv[0])) {
992 // if first param is null, ignore it, otherwise that is tokenId: number
993 if (!ParseUint32(env, argv[0], tokenId)) {
994 ParamResolveErrorThrow(env, "tokenId", "number");
995 return false;
996 }
997 }
998
999 if (!ParseString(env, argv[1], permissionName)) {
1000 ParamResolveErrorThrow(env, "permissionName", "string");
1001 return false;
1002 }
1003 }
1004
1005 // if there is no input param, that means return all tokenId and permissionName
1006 context.env = env;
1007 context.tokenId = tokenId;
1008 context.permissionName = permissionName;
1009 return true;
1010 }
1011
GetPermissionUsedTypeInfosExecute(napi_env env,void * data)1012 static void GetPermissionUsedTypeInfosExecute(napi_env env, void* data)
1013 {
1014 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionUsedTypeInfos execute.");
1015
1016 PermissionUsedTypeAsyncContext* asyncContext = reinterpret_cast<PermissionUsedTypeAsyncContext*>(data);
1017 if (asyncContext == nullptr) {
1018 return;
1019 }
1020
1021 asyncContext->retCode = PrivacyKit::GetPermissionUsedTypeInfos(asyncContext->tokenId, asyncContext->permissionName,
1022 asyncContext->results);
1023 }
1024
ConvertPermissionUsedTypeInfo(const napi_env & env,napi_value & value,const PermissionUsedTypeInfo & info)1025 static void ConvertPermissionUsedTypeInfo(const napi_env& env, napi_value& value, const PermissionUsedTypeInfo& info)
1026 {
1027 napi_value tokenIdValue;
1028 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, info.tokenId, &tokenIdValue));
1029 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "tokenId", tokenIdValue));
1030
1031 napi_value permissionNameValue;
1032 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, info.permissionName.c_str(),
1033 NAPI_AUTO_LENGTH, &permissionNameValue));
1034 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "permissionName", permissionNameValue));
1035
1036 napi_value permissionUsedTypeValue;
1037 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, info.type, &permissionUsedTypeValue));
1038 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "usedType", permissionUsedTypeValue));
1039 }
1040
ProcessPermissionUsedTypeInfoResult(const napi_env & env,napi_value & value,const std::vector<PermissionUsedTypeInfo> & results)1041 static void ProcessPermissionUsedTypeInfoResult(const napi_env& env, napi_value& value,
1042 const std::vector<PermissionUsedTypeInfo>& results)
1043 {
1044 ACCESSTOKEN_LOG_INFO(LABEL, "Size is %{public}zu", results.size());
1045 size_t index = 0;
1046 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &value));
1047 for (const auto& result : results) {
1048 napi_value permissionUsedTypeValue;
1049 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &permissionUsedTypeValue));
1050 ConvertPermissionUsedTypeInfo(env, permissionUsedTypeValue, result);
1051 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, value, index, permissionUsedTypeValue));
1052 index++;
1053 }
1054 }
1055
GetPermissionUsedTypeInfosComplete(napi_env env,napi_status status,void * data)1056 static void GetPermissionUsedTypeInfosComplete(napi_env env, napi_status status, void* data)
1057 {
1058 ACCESSTOKEN_LOG_INFO(LABEL, "GetPermissionUsedTypeInfos complete.");
1059
1060 PermissionUsedTypeAsyncContext* asyncContext = reinterpret_cast<PermissionUsedTypeAsyncContext*>(data);
1061 std::unique_ptr<PermissionUsedTypeAsyncContext> callbackPtr{asyncContext};
1062
1063 napi_value result = GetNapiNull(env);
1064 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result));
1065 ProcessPermissionUsedTypeInfoResult(env, result, asyncContext->results);
1066
1067 if (asyncContext->retCode != RET_SUCCESS) {
1068 int32_t jsCode = GetJsErrorCode(asyncContext->retCode);
1069 napi_value businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
1070 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncContext->deferred, businessError));
1071 } else {
1072 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncContext->deferred, result));
1073 }
1074 }
1075
GetPermissionUsedTypeInfos(napi_env env,napi_callback_info cbinfo)1076 napi_value GetPermissionUsedTypeInfos(napi_env env, napi_callback_info cbinfo)
1077 {
1078 ACCESSTOKEN_LOG_INFO(LABEL, "GetPermissionUsedTypeInfos begin.");
1079
1080 auto *asyncContext = new (std::nothrow) PermissionUsedTypeAsyncContext(env);
1081 if (asyncContext == nullptr) {
1082 ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
1083 return nullptr;
1084 }
1085
1086 std::unique_ptr<PermissionUsedTypeAsyncContext> callbackPtr {asyncContext};
1087 if (!ParseGetPermissionUsedType(env, cbinfo, *asyncContext)) {
1088 return nullptr;
1089 }
1090
1091 napi_value result = nullptr;
1092 NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
1093
1094 napi_value resource = nullptr;
1095 NAPI_CALL(env, napi_create_string_utf8(env, "GetPermissionUsedTypeInfos", NAPI_AUTO_LENGTH, &resource));
1096
1097 NAPI_CALL(env, napi_create_async_work(env,
1098 nullptr,
1099 resource,
1100 GetPermissionUsedTypeInfosExecute,
1101 GetPermissionUsedTypeInfosComplete,
1102 reinterpret_cast<void *>(asyncContext),
1103 &(asyncContext->asyncWork)));
1104 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->asyncWork, napi_qos_default));
1105 callbackPtr.release();
1106 return result;
1107 }
1108 } // namespace AccessToken
1109 } // namespace Security
1110 } // namespace OHOS