• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "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_array(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