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 <vector>
17 #include "privacy_kit.h"
18 #include "accesstoken_log.h"
19 #include "napi_context_common.h"
20 #include "napi_common.h"
21 #include "napi_error.h"
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 #include "privacy_error.h"
25
26 namespace OHOS {
27 namespace Security {
28 namespace AccessToken {
29 std::mutex g_lockForPermActiveChangeSubscribers;
30 std::vector<RegisterPermActiveChangeContext*> g_permActiveChangeSubscribers;
31 static constexpr size_t MAX_CALLBACK_SIZE = 200;
32 static constexpr int32_t ADD_PERMISSION_RECORD_MAX_PARAMS = 5;
33 static constexpr int32_t GET_PERMISSION_RECORD_MAX_PARAMS = 2;
34 static constexpr int32_t ON_OFF_MAX_PARAMS = 3;
35 static constexpr int32_t START_STOP_MAX_PARAMS = 3;
36
37 namespace {
38 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PRIVACY, "PermissionRecordManagerNapi"};
39 } // namespace
40
GetJsErrorCode(uint32_t errCode)41 static int32_t GetJsErrorCode(uint32_t errCode)
42 {
43 int32_t jsCode = JS_OK;
44 switch (errCode) {
45 case ERR_PARAM_INVALID:
46 jsCode = JS_ERROR_PARAM_INVALID;
47 break;
48 case ERR_SERVICE_ABNORMAL:
49 case ERR_READ_PARCEL_FAILED:
50 case ERR_WRITE_PARCEL_FAILED:
51 case ERR_IPC_PARCEL_FAILED:
52 case ERR_MALLOC_FAILED:
53 jsCode = JS_ERROR_SERVICE_NOT_RUNNING;
54 break;
55 case ERR_TOKENID_NOT_EXIST:
56 jsCode = JS_ERROR_TOKENID_NOT_EXIST;
57 break;
58 case ERR_PERMISSION_NOT_EXIST:
59 jsCode = JS_ERROR_PERMISSION_NOT_EXIST;
60 break;
61 case ERR_CALLBACK_ALREADY_EXIST:
62 case ERR_CALLBACK_NOT_EXIST:
63 case ERR_PERMISSION_ALREADY_START_USING:
64 case ERR_PERMISSION_NOT_START_USING:
65 jsCode = JS_ERROR_NOT_USE_TOGETHER;
66 break;
67 case ERR_CALLBACKS_EXCEED_LIMITATION:
68 jsCode = JS_ERROR_REGISTERS_EXCEED_LIMITATION;
69 break;
70 case ERR_PERMISSION_DENIED:
71 jsCode = JS_ERROR_PERMISSION_DENIED;
72 break;
73 default:
74 break;
75 }
76 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetJsErrorCode nativeCode(%{public}d) jsCode(%{public}d).", errCode, jsCode);
77 return jsCode;
78 }
79
ParamResolveErrorThrow(const napi_env & env,const std::string & param,const std::string & type)80 static void ParamResolveErrorThrow(const napi_env& env, const std::string& param, const std::string& type)
81 {
82 std::string errMsg = GetParamErrorMsg(param, type);
83 NAPI_CALL_RETURN_VOID(env, napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, errMsg)));
84 }
85
ParseRequestResolveSomeParam(const napi_env & env,const napi_value & value,PermissionUsedRequest & request,napi_value & property)86 static bool ParseRequestResolveSomeParam(
87 const napi_env& env, const napi_value& value, PermissionUsedRequest& request, napi_value& property)
88 {
89 property = nullptr;
90 NAPI_CALL_BASE(env, napi_get_named_property(env, value, "isRemote", &property), false) ;
91 if (!ParseBool(env, property, request.isRemote)) {
92 ParamResolveErrorThrow(env, "request:isRemote", "boolean");
93 return false;
94 }
95
96 property = nullptr;
97 NAPI_CALL_BASE(env, napi_get_named_property(env, value, "deviceId", &property), false);
98 if (!ParseString(env, property, request.deviceId)) {
99 ParamResolveErrorThrow(env, "request:deviceId", "string");
100 return false;
101 }
102 return true;
103 }
104
ReturnPromiseResult(napi_env env,const RecordManagerAsyncContext & context,napi_value result)105 static void ReturnPromiseResult(napi_env env, const RecordManagerAsyncContext& context, napi_value result)
106 {
107 if (context.retCode != RET_SUCCESS) {
108 int32_t jsCode = GetJsErrorCode(context.retCode);
109 napi_value businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
110 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, context.deferred, businessError));
111 } else {
112 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, context.deferred, result));
113 }
114 }
115
ReturnCallbackResult(napi_env env,const RecordManagerAsyncContext & context,napi_value result)116 static void ReturnCallbackResult(napi_env env, const RecordManagerAsyncContext& context, napi_value result)
117 {
118 napi_value businessError = GetNapiNull(env);
119 if (context.retCode != RET_SUCCESS) {
120 int32_t jsCode = GetJsErrorCode(context.retCode);
121 businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
122 }
123 napi_value results[ASYNC_CALL_BACK_VALUES_NUM] = { businessError, result };
124
125 napi_value callback = nullptr;
126 napi_value thisValue = nullptr;
127 napi_value thatValue = nullptr;
128 NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &thisValue));
129 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, 0, &thatValue));
130 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, context.callbackRef, &callback));
131 NAPI_CALL_RETURN_VOID(env,
132 napi_call_function(env, thisValue, callback, ASYNC_CALL_BACK_VALUES_NUM, results, &thatValue));
133 }
134
ParseAddPermissionRecord(const napi_env env,const napi_callback_info info,RecordManagerAsyncContext & asyncContext)135 static bool ParseAddPermissionRecord(
136 const napi_env env, const napi_callback_info info, RecordManagerAsyncContext& asyncContext)
137 {
138 size_t argc = ADD_PERMISSION_RECORD_MAX_PARAMS;
139 napi_value argv[ADD_PERMISSION_RECORD_MAX_PARAMS] = { nullptr };
140 napi_value thisVar = nullptr;
141 void* data = nullptr;
142
143 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data), false);
144 if (argc < ADD_PERMISSION_RECORD_MAX_PARAMS - 1) {
145 NAPI_CALL_BASE(env,
146 napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
147 return false;
148 }
149
150 asyncContext.env = env;
151 // 0: the first parameter of argv
152 if (!ParseUint32(env, argv[0], asyncContext.tokenId)) {
153 ParamResolveErrorThrow(env, "tokenID", "number");
154 return false;
155 }
156
157 // 1: the second parameter of argv
158 if (!ParseString(env, argv[1], asyncContext.permissionName)) {
159 ParamResolveErrorThrow(env, "permissionName", "string");
160 return false;
161 }
162
163 // 2: the third parameter of argv
164 if (!ParseInt32(env, argv[2], asyncContext.successCount)) {
165 ParamResolveErrorThrow(env, "successCount", "number");
166 return false;
167 }
168
169 // 3: the fourth parameter of argv
170 if (!ParseInt32(env, argv[3], asyncContext.failCount)) {
171 ParamResolveErrorThrow(env, "failCount", "number");
172 return false;
173 }
174 if (argc == ADD_PERMISSION_RECORD_MAX_PARAMS) {
175 // 4: : the fifth parameter of argv
176 if (!ParseCallback(env, argv[4], asyncContext.callbackRef)) {
177 ParamResolveErrorThrow(env, "callback", "AsyncCallback");
178 return false;
179 }
180 }
181 return true;
182 }
183
ParseStartAndStopUsingPermission(const napi_env env,const napi_callback_info info,RecordManagerAsyncContext & asyncContext)184 static bool ParseStartAndStopUsingPermission(
185 const napi_env env, const napi_callback_info info, RecordManagerAsyncContext& asyncContext)
186 {
187 size_t argc = START_STOP_MAX_PARAMS;
188 napi_value argv[START_STOP_MAX_PARAMS] = { nullptr };
189 napi_value thisVar = nullptr;
190 void* data = nullptr;
191
192 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data), false);
193 if (argc < START_STOP_MAX_PARAMS - 1) {
194 NAPI_CALL_BASE(env,
195 napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
196 return false;
197 }
198
199 asyncContext.env = env;
200 // 0: the first parameter of argv
201 if (!ParseUint32(env, argv[0], asyncContext.tokenId)) {
202 ParamResolveErrorThrow(env, "tokenId", "number");
203 return false;
204 }
205
206 // 1: the second parameter of argv
207 if (!ParseString(env, argv[1], asyncContext.permissionName)) {
208 ParamResolveErrorThrow(env, "permissionName", "string");
209 return false;
210 }
211 if (argc == START_STOP_MAX_PARAMS) {
212 // 2: the third parameter of argv
213 if (!ParseCallback(env, argv[2], asyncContext.callbackRef)) {
214 ParamResolveErrorThrow(env, "callback", "AsyncCallback");
215 return false;
216 }
217 }
218 return true;
219 }
220
ConvertDetailUsedRecord(napi_env env,napi_value value,const UsedRecordDetail & detailRecord)221 static void ConvertDetailUsedRecord(napi_env env, napi_value value, const UsedRecordDetail& detailRecord)
222 {
223 napi_value nStatus;
224 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, detailRecord.status, &nStatus));
225 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "status", nStatus));
226
227 napi_value nTimestamp;
228 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, detailRecord.timestamp, &nTimestamp));
229 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "timestamp", nTimestamp));
230
231 napi_value nAccessDuration;
232 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, detailRecord.accessDuration, &nAccessDuration));
233 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "accessDuration", nAccessDuration));
234 }
235
ConvertPermissionUsedRecord(napi_env env,napi_value value,const PermissionUsedRecord & permissionRecord)236 static void ConvertPermissionUsedRecord(napi_env env, napi_value value, const PermissionUsedRecord& permissionRecord)
237 {
238 napi_value nPermissionName;
239 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env,
240 permissionRecord.permissionName.c_str(), NAPI_AUTO_LENGTH, &nPermissionName));
241 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "permissionName", nPermissionName));
242
243 napi_value nAccessCount;
244 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, permissionRecord.accessCount, &nAccessCount));
245 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "accessCount", nAccessCount));
246
247 napi_value nRejectCount;
248 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, permissionRecord.rejectCount, &nRejectCount));
249 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "rejectCount", nRejectCount));
250
251 napi_value nLastAccessTime;
252 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, permissionRecord.lastAccessTime, &nLastAccessTime));
253 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "lastAccessTime", nLastAccessTime));
254
255 napi_value nLastRejectTime;
256 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, permissionRecord.lastRejectTime, &nLastRejectTime));
257 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "lastRejectTime", nLastRejectTime));
258
259 napi_value nLastAccessDuration;
260 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, permissionRecord.lastAccessDuration, &nLastAccessDuration));
261 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "lastAccessDuration", nLastAccessDuration));
262
263 size_t index = 0;
264 napi_value objAccessRecords;
265 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &objAccessRecords));
266 for (const auto& accRecord : permissionRecord.accessRecords) {
267 napi_value objAccessRecord;
268 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objAccessRecord));
269 ConvertDetailUsedRecord(env, objAccessRecord, accRecord);
270 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objAccessRecords, index, objAccessRecord));
271 index++;
272 }
273 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "accessRecords", objAccessRecords));
274
275 index = 0;
276 napi_value objRejectRecords;
277 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &objRejectRecords));
278 for (const auto& rejRecord : permissionRecord.rejectRecords) {
279 napi_value objRejectRecord;
280 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objRejectRecord));
281 ConvertDetailUsedRecord(env, objRejectRecord, rejRecord);
282 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objRejectRecords, index, objRejectRecord));
283 index++;
284 }
285 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "rejectRecords", objRejectRecords));
286 }
287
ConvertBundleUsedRecord(napi_env env,napi_value value,const BundleUsedRecord & bundleRecord)288 static void ConvertBundleUsedRecord(napi_env env, napi_value value, const BundleUsedRecord& bundleRecord)
289 {
290 napi_value nTokenId;
291 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, bundleRecord.tokenId, &nTokenId));
292 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "tokenId", nTokenId));
293
294 napi_value nIsRemote;
295 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, bundleRecord.isRemote, &nIsRemote));
296 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "isRemote", nIsRemote));
297
298 napi_value nDeviceId;
299 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env,
300 bundleRecord.deviceId.c_str(), NAPI_AUTO_LENGTH, &nDeviceId));
301 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "deviceId", nDeviceId));
302
303 napi_value nBundleName;
304 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env,
305 bundleRecord.bundleName.c_str(), NAPI_AUTO_LENGTH, &nBundleName));
306 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "bundleName", nBundleName));
307 size_t index = 0;
308 napi_value objPermissionRecords;
309 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &objPermissionRecords));
310 for (const auto& permRecord : bundleRecord.permissionRecords) {
311 napi_value objPermissionRecord;
312 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objPermissionRecord));
313 ConvertPermissionUsedRecord(env, objPermissionRecord, permRecord);
314 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objPermissionRecords, index, objPermissionRecord));
315 index++;
316 }
317 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "permissionRecords", objPermissionRecords));
318 }
319
ProcessRecordResult(napi_env env,napi_value value,const PermissionUsedResult & result)320 static void ProcessRecordResult(napi_env env, napi_value value, const PermissionUsedResult& result)
321 {
322 napi_value nBeginTimestamp;
323 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, result.beginTimeMillis, &nBeginTimestamp));
324 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "beginTime", nBeginTimestamp));
325
326 napi_value nEndTimestamp;
327 NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, result.endTimeMillis, &nEndTimestamp));
328 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "endTime", nEndTimestamp));
329
330 size_t index = 0;
331 napi_value objBundleRecords;
332 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &objBundleRecords));
333 for (const auto& bundleRecord : result.bundleRecords) {
334 napi_value objBundleRecord;
335 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objBundleRecord));
336 ConvertBundleUsedRecord(env, objBundleRecord, bundleRecord);
337 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objBundleRecords, index, objBundleRecord));
338 index++;
339 }
340 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "bundleRecords", objBundleRecords));
341 }
342
ParseRequest(const napi_env & env,const napi_value & value,PermissionUsedRequest & request)343 static bool ParseRequest(const napi_env& env, const napi_value& value, PermissionUsedRequest& request)
344 {
345 if (!CheckType(env, value, napi_object)) {
346 return false;
347 }
348 napi_value property = nullptr;
349 NAPI_CALL_BASE(env, napi_get_named_property(env, value, "tokenId", &property), false);
350 if (!ParseUint32(env, property, request.tokenId)) {
351 ParamResolveErrorThrow(env, "request:tokenId", "number");
352 return false;
353 }
354
355 if (!ParseRequestResolveSomeParam(env, value, request, property)) {
356 return false;
357 }
358
359 property = nullptr;
360 NAPI_CALL_BASE(env, napi_get_named_property(env, value, "bundleName", &property), false);
361 if (!ParseString(env, property, request.bundleName)) {
362 ParamResolveErrorThrow(env, "request:bundleName", "string");
363 return false;
364 }
365
366 property = nullptr;
367 NAPI_CALL_BASE(env, napi_get_named_property(env, value, "beginTime", &property), false);
368 if (!ParseInt64(env, property, request.beginTimeMillis)) {
369 ParamResolveErrorThrow(env, "request:beginTime", "number");
370 return false;
371 }
372
373 property = nullptr;
374 NAPI_CALL_BASE(env, napi_get_named_property(env, value, "endTime", &property), false);
375 if (!ParseInt64(env, property, request.endTimeMillis)) {
376 ParamResolveErrorThrow(env, "request:endTime", "number");
377 return false;
378 }
379
380 property = nullptr;
381 NAPI_CALL_BASE(env, napi_get_named_property(env, value, "permissionNames", &property), false);
382 if (!ParseStringArray(env, property, request.permissionList)) {
383 ParamResolveErrorThrow(env, "request:permissionNames", "Array<string>");
384 return false;
385 }
386
387 property = nullptr;
388 NAPI_CALL_BASE(env, napi_get_named_property(env, value, "flag", &property), false);
389 int32_t flag;
390 if (!ParseInt32(env, property, flag)) {
391 ParamResolveErrorThrow(env, "request:flag", "number");
392 return false;
393 }
394 request.flag = static_cast<PermissionUsageFlagEnum>(flag);
395
396 return true;
397 }
398
ParseGetPermissionUsedRecords(const napi_env env,const napi_callback_info info,RecordManagerAsyncContext & asyncContext)399 static bool ParseGetPermissionUsedRecords(
400 const napi_env env, const napi_callback_info info, RecordManagerAsyncContext& asyncContext)
401 {
402 size_t argc = GET_PERMISSION_RECORD_MAX_PARAMS;
403 napi_value argv[GET_PERMISSION_RECORD_MAX_PARAMS] = { nullptr };
404 napi_value thisVar = nullptr;
405 void* data = nullptr;
406 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data), false);
407 if (argc < GET_PERMISSION_RECORD_MAX_PARAMS - 1) {
408 NAPI_CALL_BASE(env,
409 napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
410 return false;
411 }
412
413 asyncContext.env = env;
414
415 // 0: the first parameter of argv
416 if (!ParseRequest(env, argv[0], asyncContext.request)) {
417 return false;
418 }
419
420 if (argc == GET_PERMISSION_RECORD_MAX_PARAMS) {
421 // 1: the second parameter of argv
422 if (!ParseCallback(env, argv[1], asyncContext.callbackRef)) {
423 ParamResolveErrorThrow(env, "callback", "AsyncCallback");
424 return false;
425 }
426 }
427 return true;
428 }
429
AddPermissionUsedRecordExecute(napi_env env,void * data)430 static void AddPermissionUsedRecordExecute(napi_env env, void* data)
431 {
432 ACCESSTOKEN_LOG_DEBUG(LABEL, "AddPermissionUsedRecord execute.");
433 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
434 if (asyncContext == nullptr) {
435 return;
436 }
437
438 asyncContext->retCode = PrivacyKit::AddPermissionUsedRecord(asyncContext->tokenId,
439 asyncContext->permissionName, asyncContext->successCount, asyncContext->failCount);
440 }
441
AddPermissionUsedRecordComplete(napi_env env,napi_status status,void * data)442 static void AddPermissionUsedRecordComplete(napi_env env, napi_status status, void* data)
443 {
444 ACCESSTOKEN_LOG_DEBUG(LABEL, "AddPermissionUsedRecord complete.");
445 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
446 if (asyncContext == nullptr) {
447 return;
448 }
449
450 std::unique_ptr<RecordManagerAsyncContext> callbackPtr {asyncContext};
451 napi_value result = GetNapiNull(env);
452 if (asyncContext->deferred != nullptr) {
453 ReturnPromiseResult(env, *asyncContext, result);
454 } else {
455 ReturnCallbackResult(env, *asyncContext, result);
456 }
457 }
458
AddPermissionUsedRecord(napi_env env,napi_callback_info cbinfo)459 napi_value AddPermissionUsedRecord(napi_env env, napi_callback_info cbinfo)
460 {
461 ACCESSTOKEN_LOG_DEBUG(LABEL, "AddPermissionUsedRecord begin.");
462
463 auto *asyncContext = new (std::nothrow) RecordManagerAsyncContext(env);
464 if (asyncContext == nullptr) {
465 ACCESSTOKEN_LOG_ERROR(LABEL, "new struct fail.");
466 return nullptr;
467 }
468
469 std::unique_ptr<RecordManagerAsyncContext> callbackPtr {asyncContext};
470 if (!ParseAddPermissionRecord(env, cbinfo, *asyncContext)) {
471 return nullptr;
472 }
473
474 napi_value result = nullptr;
475 if (asyncContext->callbackRef == nullptr) {
476 NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
477 } else {
478 NAPI_CALL(env, napi_get_undefined(env, &result));
479 }
480
481 napi_value resource = nullptr;
482 NAPI_CALL(env, napi_create_string_utf8(env, "AddPermissionUsedRecord", NAPI_AUTO_LENGTH, &resource));
483
484 NAPI_CALL(env, napi_create_async_work(env,
485 nullptr,
486 resource,
487 AddPermissionUsedRecordExecute,
488 AddPermissionUsedRecordComplete,
489 reinterpret_cast<void *>(asyncContext),
490 &(asyncContext->asyncWork)));
491 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->asyncWork));
492 callbackPtr.release();
493 return result;
494 }
495
StartUsingPermissionExecute(napi_env env,void * data)496 static void StartUsingPermissionExecute(napi_env env, void* data)
497 {
498 ACCESSTOKEN_LOG_DEBUG(LABEL, "StartUsingPermission execute.");
499 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
500 if (asyncContext == nullptr) {
501 return;
502 }
503
504 asyncContext->retCode = PrivacyKit::StartUsingPermission(asyncContext->tokenId,
505 asyncContext->permissionName);
506 }
507
StartUsingPermissionComplete(napi_env env,napi_status status,void * data)508 static void StartUsingPermissionComplete(napi_env env, napi_status status, void* data)
509 {
510 ACCESSTOKEN_LOG_DEBUG(LABEL, "StartUsingPermission complete.");
511 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
512 if (asyncContext == nullptr) {
513 return;
514 }
515
516 std::unique_ptr<RecordManagerAsyncContext> callbackPtr{asyncContext};
517 napi_value result = GetNapiNull(env);
518 if (asyncContext->deferred != nullptr) {
519 ReturnPromiseResult(env, *asyncContext, result);
520 } else {
521 ReturnCallbackResult(env, *asyncContext, result);
522 }
523 }
524
StartUsingPermission(napi_env env,napi_callback_info cbinfo)525 napi_value StartUsingPermission(napi_env env, napi_callback_info cbinfo)
526 {
527 ACCESSTOKEN_LOG_DEBUG(LABEL, "StartUsingPermission begin.");
528 auto *asyncContext = new (std::nothrow) RecordManagerAsyncContext(env);
529 if (asyncContext == nullptr) {
530 ACCESSTOKEN_LOG_ERROR(LABEL, "new struct fail.");
531 return nullptr;
532 }
533
534 std::unique_ptr<RecordManagerAsyncContext> callbackPtr {asyncContext};
535 if (!ParseStartAndStopUsingPermission(env, cbinfo, *asyncContext)) {
536 return nullptr;
537 }
538
539 napi_value result = nullptr;
540 if (asyncContext->callbackRef == nullptr) {
541 NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
542 } else {
543 NAPI_CALL(env, napi_get_undefined(env, &result));
544 }
545
546 napi_value resource = nullptr;
547 NAPI_CALL(env, napi_create_string_utf8(env, "StartUsingPermission", NAPI_AUTO_LENGTH, &resource));
548
549 NAPI_CALL(env, napi_create_async_work(env,
550 nullptr,
551 resource,
552 StartUsingPermissionExecute,
553 StartUsingPermissionComplete,
554 reinterpret_cast<void *>(asyncContext),
555 &(asyncContext->asyncWork)));
556 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->asyncWork));
557 callbackPtr.release();
558 return result;
559 }
560
StopUsingPermissionExecute(napi_env env,void * data)561 static void StopUsingPermissionExecute(napi_env env, void* data)
562 {
563 ACCESSTOKEN_LOG_DEBUG(LABEL, "StopUsingPermission execute.");
564 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
565 if (asyncContext == nullptr) {
566 return;
567 }
568
569 asyncContext->retCode = PrivacyKit::StopUsingPermission(asyncContext->tokenId,
570 asyncContext->permissionName);
571 }
572
StopUsingPermissionComplete(napi_env env,napi_status status,void * data)573 static void StopUsingPermissionComplete(napi_env env, napi_status status, void* data)
574 {
575 ACCESSTOKEN_LOG_DEBUG(LABEL, "StopUsingPermission complete.");
576 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
577 if (asyncContext == nullptr) {
578 return;
579 }
580
581 std::unique_ptr<RecordManagerAsyncContext> callbackPtr{asyncContext};
582 napi_value result = GetNapiNull(env);
583
584 if (asyncContext->deferred != nullptr) {
585 ReturnPromiseResult(env, *asyncContext, result);
586 } else {
587 ReturnCallbackResult(env, *asyncContext, result);
588 }
589 }
590
StopUsingPermission(napi_env env,napi_callback_info cbinfo)591 napi_value StopUsingPermission(napi_env env, napi_callback_info cbinfo)
592 {
593 ACCESSTOKEN_LOG_DEBUG(LABEL, "StopUsingPermission begin.");
594
595 auto *asyncContext = new (std::nothrow) RecordManagerAsyncContext(env);
596 if (asyncContext == nullptr) {
597 ACCESSTOKEN_LOG_ERROR(LABEL, "new struct fail.");
598 return nullptr;
599 }
600
601 std::unique_ptr<RecordManagerAsyncContext> callbackPtr {asyncContext};
602 if (!ParseStartAndStopUsingPermission(env, cbinfo, *asyncContext)) {
603 return nullptr;
604 }
605
606 napi_value result = nullptr;
607 if (asyncContext->callbackRef == nullptr) {
608 NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
609 } else {
610 NAPI_CALL(env, napi_get_undefined(env, &result));
611 }
612
613 napi_value resource = nullptr;
614 NAPI_CALL(env, napi_create_string_utf8(env, "StopUsingPermission", NAPI_AUTO_LENGTH, &resource));
615
616 NAPI_CALL(env, napi_create_async_work(env,
617 nullptr,
618 resource,
619 StopUsingPermissionExecute,
620 StopUsingPermissionComplete,
621 reinterpret_cast<void *>(asyncContext),
622 &(asyncContext->asyncWork)));
623 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->asyncWork));
624 callbackPtr.release();
625 return result;
626 }
627
GetPermissionUsedRecordsExecute(napi_env env,void * data)628 static void GetPermissionUsedRecordsExecute(napi_env env, void* data)
629 {
630 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionUsedRecords execute.");
631 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
632 if (asyncContext == nullptr) {
633 return;
634 }
635
636 asyncContext->retCode = PrivacyKit::GetPermissionUsedRecords(asyncContext->request, asyncContext->result);
637 }
638
GetPermissionUsedRecordsComplete(napi_env env,napi_status status,void * data)639 static void GetPermissionUsedRecordsComplete(napi_env env, napi_status status, void* data)
640 {
641 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionUsedRecords complete.");
642 RecordManagerAsyncContext* asyncContext = reinterpret_cast<RecordManagerAsyncContext*>(data);
643 if (asyncContext == nullptr) {
644 return;
645 }
646
647 std::unique_ptr<RecordManagerAsyncContext> callbackPtr{asyncContext};
648 napi_value result = GetNapiNull(env);
649 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result));
650 ProcessRecordResult(env, result, asyncContext->result);
651 if (asyncContext->deferred != nullptr) {
652 ReturnPromiseResult(env, *asyncContext, result);
653 } else {
654 ReturnCallbackResult(env, *asyncContext, result);
655 }
656 }
657
GetPermissionUsedRecords(napi_env env,napi_callback_info cbinfo)658 napi_value GetPermissionUsedRecords(napi_env env, napi_callback_info cbinfo)
659 {
660 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionUsedRecords begin.");
661 auto *asyncContext = new (std::nothrow) RecordManagerAsyncContext(env);
662 if (asyncContext == nullptr) {
663 ACCESSTOKEN_LOG_ERROR(LABEL, "new struct fail.");
664 return nullptr;
665 }
666
667 std::unique_ptr<RecordManagerAsyncContext> callbackPtr {asyncContext};
668 if (!ParseGetPermissionUsedRecords(env, cbinfo, *asyncContext)) {
669 return nullptr;
670 }
671
672 napi_value result = nullptr;
673 if (asyncContext->callbackRef == nullptr) {
674 NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
675 } else {
676 NAPI_CALL(env, napi_get_undefined(env, &result));
677 }
678
679 napi_value resource = nullptr;
680 NAPI_CALL(env, napi_create_string_utf8(env, "GetPermissionUsedRecords", NAPI_AUTO_LENGTH, &resource));
681
682 NAPI_CALL(env, napi_create_async_work(env,
683 nullptr,
684 resource,
685 GetPermissionUsedRecordsExecute,
686 GetPermissionUsedRecordsComplete,
687 reinterpret_cast<void *>(asyncContext),
688 &(asyncContext->asyncWork)));
689 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->asyncWork));
690 callbackPtr.release();
691 return result;
692 }
693
ParseInputToRegister(const napi_env env,const napi_callback_info cbInfo,RegisterPermActiveChangeContext & registerPermActiveChangeContext)694 static bool ParseInputToRegister(const napi_env env, const napi_callback_info cbInfo,
695 RegisterPermActiveChangeContext& registerPermActiveChangeContext)
696 {
697 size_t argc = ON_OFF_MAX_PARAMS;
698 napi_value argv[ON_OFF_MAX_PARAMS] = {nullptr};
699 napi_value thisVar = nullptr;
700 napi_ref callback = nullptr;
701 NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr), false);
702 if (argc < ON_OFF_MAX_PARAMS) {
703 NAPI_CALL_BASE(
704 env, napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
705 return false;
706 }
707
708 std::string type;
709 // 0: the first parameter of argv
710 if (!ParseString(env, argv[0], type)) {
711 ParamResolveErrorThrow(env, "type", "string");
712 return false;
713 }
714 std::vector<std::string> permList;
715 // 1: the second parameter of argv
716 if (!ParseStringArray(env, argv[1], permList)) {
717 ParamResolveErrorThrow(env, "permList", "Array<string>");
718 return false;
719 }
720 std::sort(permList.begin(), permList.end());
721 // 2: the third parameter of argv
722 if (!ParseCallback(env, argv[2], callback)) {
723 ParamResolveErrorThrow(env, "callback", "AsyncCallback");
724 return false;
725 }
726 registerPermActiveChangeContext.env = env;
727 registerPermActiveChangeContext.callbackRef = callback;
728 registerPermActiveChangeContext.type = type;
729 registerPermActiveChangeContext.subscriber = std::make_shared<PermActiveStatusPtr>(permList);
730 registerPermActiveChangeContext.subscriber->SetEnv(env);
731 registerPermActiveChangeContext.subscriber->SetCallbackRef(callback);
732 return true;
733 }
734
ParseInputToUnregister(const napi_env env,const napi_callback_info cbInfo,UnregisterPermActiveChangeContext & unregisterPermActiveChangeContext)735 static bool ParseInputToUnregister(const napi_env env, const napi_callback_info cbInfo,
736 UnregisterPermActiveChangeContext& unregisterPermActiveChangeContext)
737 {
738 size_t argc = ON_OFF_MAX_PARAMS;
739 napi_value argv[ON_OFF_MAX_PARAMS] = {nullptr};
740 napi_value thisVar = nullptr;
741 napi_ref callback = nullptr;
742 NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr), false);
743 if (argc < ON_OFF_MAX_PARAMS - 1) {
744 NAPI_CALL_BASE(
745 env, napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
746 return false;
747 }
748
749 std::string type;
750 // 0: the first parameter of argv
751 if (!ParseString(env, argv[0], type)) {
752 ParamResolveErrorThrow(env, "permList", "Array<string>");
753 return false;
754 }
755 // 1: the second parameter of argv
756 std::vector<std::string> permList;
757 if (!ParseStringArray(env, argv[1], permList)) {
758 ParamResolveErrorThrow(env, "permList", "Array<string>");
759 return false;
760 }
761 std::sort(permList.begin(), permList.end());
762 if (argc == ON_OFF_MAX_PARAMS) {
763 // 2: the first parameter of argv
764 if (!ParseCallback(env, argv[2], callback)) {
765 ParamResolveErrorThrow(env, "callback", "AsyncCallback");
766 return false;
767 }
768 }
769 unregisterPermActiveChangeContext.env = env;
770 unregisterPermActiveChangeContext.callbackRef = callback;
771 unregisterPermActiveChangeContext.type = type;
772 unregisterPermActiveChangeContext.permList = permList;
773 return true;
774 }
775
IsExistRegister(const PermActiveChangeContext * permActiveChangeContext)776 static bool IsExistRegister(const PermActiveChangeContext* permActiveChangeContext)
777 {
778 std::vector<std::string> targetPermList;
779 permActiveChangeContext->subscriber->GetPermList(targetPermList);
780 std::lock_guard<std::mutex> lock(g_lockForPermActiveChangeSubscribers);
781 for (const auto& item : g_permActiveChangeSubscribers) {
782 std::vector<std::string> permList;
783 item->subscriber->GetPermList(permList);
784 if (permList == targetPermList) {
785 return true;
786 }
787 }
788 return false;
789 }
790
DeleteRegisterInVector(PermActiveChangeContext * permActiveChangeContext)791 static void DeleteRegisterInVector(PermActiveChangeContext* permActiveChangeContext)
792 {
793 std::vector<std::string> targetPermList;
794 permActiveChangeContext->subscriber->GetPermList(targetPermList);
795 std::lock_guard<std::mutex> lock(g_lockForPermActiveChangeSubscribers);
796 auto item = g_permActiveChangeSubscribers.begin();
797 while (item != g_permActiveChangeSubscribers.end()) {
798 std::vector<std::string> permList;
799 (*item)->subscriber->GetPermList(permList);
800 if (permList == targetPermList) {
801 delete *item;
802 *item = nullptr;
803 g_permActiveChangeSubscribers.erase(item);
804 return;
805 } else {
806 ++item;
807 }
808 }
809 }
810
FindAndGetSubscriber(UnregisterPermActiveChangeContext * unregisterPermActiveChangeContext)811 static bool FindAndGetSubscriber(UnregisterPermActiveChangeContext* unregisterPermActiveChangeContext)
812 {
813 std::vector<std::string> targetPermList = unregisterPermActiveChangeContext->permList;
814 std::lock_guard<std::mutex> lock(g_lockForPermActiveChangeSubscribers);
815 for (const auto& item : g_permActiveChangeSubscribers) {
816 std::vector<std::string> permList;
817 item->subscriber->GetPermList(permList);
818 if (permList == targetPermList) {
819 // targetCallback != nullptr, unregister the subscriber with same permList and callback
820 unregisterPermActiveChangeContext->subscriber = item->subscriber;
821 return true;
822 }
823 }
824 return false;
825 }
826
RegisterPermActiveChangeCallback(napi_env env,napi_callback_info cbInfo)827 napi_value RegisterPermActiveChangeCallback(napi_env env, napi_callback_info cbInfo)
828 {
829 RegisterPermActiveChangeContext* registerPermActiveChangeContext =
830 new (std::nothrow) RegisterPermActiveChangeContext();
831 if (registerPermActiveChangeContext == nullptr) {
832 ACCESSTOKEN_LOG_ERROR(LABEL, "insufficient memory for subscribeCBInfo!");
833 return nullptr;
834 }
835 std::unique_ptr<RegisterPermActiveChangeContext> callbackPtr {registerPermActiveChangeContext};
836 if (!ParseInputToRegister(env, cbInfo, *registerPermActiveChangeContext)) {
837 return nullptr;
838 }
839 if (IsExistRegister(registerPermActiveChangeContext)) {
840 ACCESSTOKEN_LOG_ERROR(LABEL, "Subscribe failed. The current subscriber has been existed");
841 std::string errMsg = GetErrorMessage(JsErrorCode::JS_ERROR_PARAM_INVALID);
842 NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_INVALID, errMsg)));
843 return nullptr;
844 }
845 int32_t result = PrivacyKit::RegisterPermActiveStatusCallback(registerPermActiveChangeContext->subscriber);
846 if (result != RET_SUCCESS) {
847 ACCESSTOKEN_LOG_ERROR(LABEL, "RegisterPermActiveStatusCallback failed");
848 int32_t jsCode = GetJsErrorCode(result);
849 std::string errMsg = GetErrorMessage(jsCode);
850 NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, jsCode, errMsg)));
851 return nullptr;
852 }
853 {
854 std::lock_guard<std::mutex> lock(g_lockForPermActiveChangeSubscribers);
855 if (g_permActiveChangeSubscribers.size() >= MAX_CALLBACK_SIZE) {
856 ACCESSTOKEN_LOG_ERROR(LABEL, "subscribers size has reached max value");
857 return nullptr;
858 }
859 g_permActiveChangeSubscribers.emplace_back(registerPermActiveChangeContext);
860 }
861 callbackPtr.release();
862 return nullptr;
863 }
864
UnregisterPermActiveChangeCallback(napi_env env,napi_callback_info cbInfo)865 napi_value UnregisterPermActiveChangeCallback(napi_env env, napi_callback_info cbInfo)
866 {
867 UnregisterPermActiveChangeContext* unregisterPermActiveChangeContext =
868 new (std::nothrow) UnregisterPermActiveChangeContext();
869 if (unregisterPermActiveChangeContext == nullptr) {
870 ACCESSTOKEN_LOG_ERROR(LABEL, "insufficient memory for subscribeCBInfo!");
871 return nullptr;
872 }
873 std::unique_ptr<UnregisterPermActiveChangeContext> callbackPtr {unregisterPermActiveChangeContext};
874 if (!ParseInputToUnregister(env, cbInfo, *unregisterPermActiveChangeContext)) {
875 return nullptr;
876 }
877 if (!FindAndGetSubscriber(unregisterPermActiveChangeContext)) {
878 ACCESSTOKEN_LOG_ERROR(LABEL, "Unsubscribe failed. The current subscriber does not exist");
879 std::string errMsg = GetErrorMessage(JsErrorCode::JS_ERROR_PARAM_INVALID);
880 NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_INVALID, errMsg)));
881 return nullptr;
882 }
883 int32_t result = PrivacyKit::UnRegisterPermActiveStatusCallback(unregisterPermActiveChangeContext->subscriber);
884 if (result == RET_SUCCESS) {
885 DeleteRegisterInVector(unregisterPermActiveChangeContext);
886 } else {
887 ACCESSTOKEN_LOG_ERROR(LABEL, "UnregisterPermActiveChangeCompleted failed");
888 int32_t jsCode = GetJsErrorCode(result);
889 std::string errMsg = GetErrorMessage(jsCode);
890 NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, jsCode, errMsg)));
891 }
892 return nullptr;
893 }
894 } // namespace AccessToken
895 } // namespace Security
896 } // namespace OHOS