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