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