1 /*
2 * Copyright (c) 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 "grant_permissions.h"
16
17 #include <string>
18 #include <vector>
19
20 #include "access_token.h"
21 #include "accesstoken_kit.h"
22 #include "ipc_skeleton.h"
23 #include "js_native_api.h"
24 #include "log.h"
25 #include "n_napi.h"
26 #include "tokenid_kit.h"
27
28 namespace OHOS {
29 namespace AppFileService {
30 namespace ModuleFileShare {
31 using namespace OHOS::FileManagement::LibN;
32 using namespace OHOS::Security::AccessToken;
33 using namespace std;
34
GetErrData(napi_env env,deque<struct PolicyErrorResult> & errorResults)35 static napi_value GetErrData(napi_env env, deque<struct PolicyErrorResult> &errorResults)
36 {
37 napi_value res = nullptr;
38 napi_status status = napi_create_array(env, &res);
39 if (status != napi_ok) {
40 LOGE("Failed to create array");
41 return nullptr;
42 }
43 size_t index = 0;
44 for (auto &iter : errorResults) {
45 NVal obj = NVal::CreateObject(env);
46 obj.AddProp("uri", NVal::CreateUTF8String(env, iter.uri).val_);
47 obj.AddProp("code", NVal::CreateInt32(env, iter.code).val_);
48 obj.AddProp("message", NVal::CreateUTF8String(env, iter.message).val_);
49 status = napi_set_element(env, res, index++, obj.val_);
50 if (status != napi_ok) {
51 LOGE("Failed to set element on data");
52 return nullptr;
53 }
54 }
55 return res;
56 }
57
GetResultData(napi_env env,const vector<bool> & results)58 static napi_value GetResultData(napi_env env, const vector<bool> &results)
59 {
60 napi_value res = nullptr;
61 napi_status status = napi_create_array(env, &res);
62 if (status != napi_ok) {
63 LOGE("Failed to create array");
64 return nullptr;
65 }
66 size_t index = 0;
67 for (const auto &iter : results) {
68 napi_value value;
69 napi_get_boolean(env, iter, &value);
70 status = napi_set_element(env, res, index++, value);
71 if (status != napi_ok) {
72 LOGE("Failed to set element on data");
73 return nullptr;
74 }
75 }
76 return res;
77 }
78
GetUriPolicy(napi_env env,napi_value agrv,std::vector<UriPolicyInfo> & uriPolicies,uint32_t index)79 static napi_status GetUriPolicy(napi_env env, napi_value agrv, std::vector<UriPolicyInfo> &uriPolicies, uint32_t index)
80 {
81 napi_value object;
82 napi_status status = napi_get_element(env, agrv, index, &object);
83 if (status != napi_ok) {
84 LOGE("get element failed");
85 return status;
86 }
87 napi_value uriValue;
88 napi_value modeValue;
89 status = napi_get_named_property(env, object, "uri", &uriValue);
90 if (status != napi_ok) {
91 LOGE("get named property failed");
92 return status;
93 }
94 status = napi_get_named_property(env, object, "operationMode", &modeValue);
95 if (status != napi_ok) {
96 LOGE("get named property failed");
97 return status;
98 }
99 auto [succStr, str, ignore] = NVal(env, uriValue).ToUTF8String();
100 auto [succMode, mode] = NVal(env, modeValue).ToUint32();
101 if (!succStr || !succMode) {
102 LOGE("the argument error, succStr = %{public}d, succMode = %{public}d", succStr, succMode);
103 return napi_invalid_arg;
104 }
105 UriPolicyInfo uriPolicy {.uri = str.get(), .mode = mode};
106 uriPolicies.emplace_back(uriPolicy);
107 return napi_ok;
108 }
109
GetUriPoliciesArg(napi_env env,napi_value agrv,std::vector<UriPolicyInfo> & uriPolicies)110 static napi_status GetUriPoliciesArg(napi_env env, napi_value agrv, std::vector<UriPolicyInfo> &uriPolicies)
111 {
112 uint32_t count;
113 napi_status status = napi_get_array_length(env, agrv, &count);
114 if (status != napi_ok) {
115 LOGE("get array length failed");
116 return status;
117 }
118 if (count > MAX_ARRAY_SIZE) {
119 LOGE("The length of the array is extra-long");
120 return napi_invalid_arg;
121 }
122 for (uint32_t i = 0; i < count; i++) {
123 napi_handle_scope scope;
124 status = napi_open_handle_scope(env, &scope);
125 if (status != napi_ok) {
126 return status;
127 }
128 status = GetUriPolicy(env, agrv, uriPolicies, i);
129 if (status != napi_ok) {
130 napi_close_handle_scope(env, scope);
131 return status;
132 }
133 status = napi_close_handle_scope(env, scope);
134 if (status != napi_ok) {
135 return status;
136 }
137 }
138 return napi_ok;
139 }
140
CheckPathArray(napi_env env,napi_value agrv,uint32_t & count)141 static napi_status CheckPathArray(napi_env env, napi_value agrv, uint32_t &count)
142 {
143 napi_status status = napi_get_array_length(env, agrv, &count);
144 if (status != napi_ok) {
145 LOGE("get array length failed");
146 return status;
147 }
148 if (count == 0 || count > MAX_ARRAY_SIZE) {
149 LOGE("The length of the array is extra-long or length is 0");
150 return napi_invalid_arg;
151 }
152 return napi_ok;
153 }
154
GetPathPolicy(napi_env env,napi_value agrv,std::vector<PathPolicyInfo> & pathPolicies,uint32_t index)155 static napi_status GetPathPolicy(napi_env env,
156 napi_value agrv,
157 std::vector<PathPolicyInfo> &pathPolicies,
158 uint32_t index)
159 {
160 napi_value object;
161 napi_status status = napi_get_element(env, agrv, index, &object);
162 if (status != napi_ok) {
163 LOGE("get element failed");
164 return status;
165 }
166 napi_value pathValue;
167 napi_value modeValue;
168 status = napi_get_named_property(env, object, "path", &pathValue);
169 if (status != napi_ok) {
170 LOGE("get named property failed");
171 return status;
172 }
173 status = napi_get_named_property(env, object, "operationMode", &modeValue);
174 if (status != napi_ok) {
175 LOGE("get named property failed");
176 return status;
177 }
178 auto [succStr, str, ignore] = NVal(env, pathValue).ToUTF8String();
179 auto [succMode, mode] = NVal(env, modeValue).ToUint32();
180 if (!succStr || !succMode) {
181 LOGE("the argument error, succStr = %{public}d, succMode = %{public}d", succStr, succMode);
182 return napi_invalid_arg;
183 }
184 PathPolicyInfo pathPolicy {.path = str.get(), .mode = mode};
185 pathPolicies.emplace_back(pathPolicy);
186 return napi_ok;
187 }
188
GetPathPoliciesArg(napi_env env,napi_value agrv,std::vector<PathPolicyInfo> & pathPolicies)189 static napi_status GetPathPoliciesArg(napi_env env, napi_value agrv, std::vector<PathPolicyInfo> &pathPolicies)
190 {
191 uint32_t count;
192 napi_status status = CheckPathArray(env, agrv, count);
193 if (status != napi_ok) {
194 return status;
195 }
196 for (uint32_t i = 0; i < count; i++) {
197 napi_handle_scope scope;
198 status = napi_open_handle_scope(env, &scope);
199 if (status != napi_ok) {
200 LOGE("open handle scope failed");
201 return status;
202 }
203 status = GetPathPolicy(env, agrv, pathPolicies, i);
204 if (status != napi_ok) {
205 napi_close_handle_scope(env, scope);
206 return status;
207 }
208 status = napi_close_handle_scope(env, scope);
209 if (status != napi_ok) {
210 return status;
211 }
212 }
213 return napi_ok;
214 }
215
IsSystemApp()216 static bool IsSystemApp()
217 {
218 uint64_t fullTokenId = OHOS::IPCSkeleton::GetCallingFullTokenID();
219 return TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
220 }
221
PersistPermission(napi_env env,napi_callback_info info)222 napi_value PersistPermission(napi_env env, napi_callback_info info)
223 {
224 NFuncArg funcArg(env, info);
225 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
226 LOGE("PersistPermission Number of arguments unmatched");
227 NError(E_PARAMS).ThrowErr(env);
228 return nullptr;
229 }
230 std::vector<UriPolicyInfo> uriPolicies;
231 if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
232 NError(E_PARAMS).ThrowErr(env);
233 return nullptr;
234 }
235 shared_ptr<PolicyErrorArgs> arg = make_shared<PolicyErrorArgs>();
236 if (arg == nullptr) {
237 LOGE("Make_shared is failed");
238 std::tuple<uint32_t, std::string> errInfo =
239 std::make_tuple(E_UNKNOWN_ERROR, "Out of memory, execute make_shared function failed");
240 ErrParam errorParam = [errInfo]() { return errInfo; };
241 NError(errorParam).ThrowErr(env);
242 return nullptr;
243 }
244 auto cbExec = [uriPolicies, arg]() -> NError {
245 arg->errNo = FilePermission::PersistPermission(uriPolicies, arg->errorResults);
246 return NError(arg->errNo);
247 };
248 auto cbCompl = [arg](napi_env env, NError err) -> NVal {
249 if (err) {
250 if (arg->errNo == EPERM) {
251 napi_value data = err.GetNapiErr(env);
252 napi_set_named_property(env, data, FILEIO_TAG_ERR_DATA.c_str(), GetErrData(env, arg->errorResults));
253 return NVal(env, data);
254 }
255 return {env, err.GetNapiErr(env)};
256 }
257 return NVal::CreateUndefined(env);
258 };
259 const string procedureName = "persist_permission";
260 NVal thisVar(env, funcArg.GetThisVar());
261 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
262 }
263
RevokePermission(napi_env env,napi_callback_info info)264 napi_value RevokePermission(napi_env env, napi_callback_info info)
265 {
266 NFuncArg funcArg(env, info);
267 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
268 LOGE("RevokePermission Number of arguments unmatched");
269 NError(E_PARAMS).ThrowErr(env);
270 return nullptr;
271 }
272 std::vector<UriPolicyInfo> uriPolicies;
273 if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
274 NError(E_PARAMS).ThrowErr(env);
275 return nullptr;
276 }
277 shared_ptr<PolicyErrorArgs> arg = make_shared<PolicyErrorArgs>();
278 if (arg == nullptr) {
279 LOGE("Make_shared is failed");
280 std::tuple<uint32_t, std::string> errInfo =
281 std::make_tuple(E_UNKNOWN_ERROR, "Out of memory, execute make_shared function failed");
282 ErrParam errorParam = [errInfo]() { return errInfo; };
283 NError(errorParam).ThrowErr(env);
284 return nullptr;
285 }
286 auto cbExec = [uriPolicies, arg]() -> NError {
287 arg->errNo = FilePermission::RevokePermission(uriPolicies, arg->errorResults);
288 return NError(arg->errNo);
289 };
290 auto cbCompl = [arg](napi_env env, NError err) -> NVal {
291 if (err) {
292 if (arg->errNo == EPERM) {
293 napi_value data = err.GetNapiErr(env);
294 napi_set_named_property(env, data, FILEIO_TAG_ERR_DATA.c_str(), GetErrData(env, arg->errorResults));
295 return NVal(env, data);
296 }
297 return {env, err.GetNapiErr(env)};
298 }
299 return NVal::CreateUndefined(env);
300 };
301 const string procedureName = "revoke_permission";
302 NVal thisVar(env, funcArg.GetThisVar());
303 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
304 }
305
ActivatePermission(napi_env env,napi_callback_info info)306 napi_value ActivatePermission(napi_env env, napi_callback_info info)
307 {
308 NFuncArg funcArg(env, info);
309 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
310 LOGE("ActivatePermission Number of arguments unmatched");
311 NError(E_PARAMS).ThrowErr(env);
312 return nullptr;
313 }
314 std::vector<UriPolicyInfo> uriPolicies;
315 if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
316 NError(E_PARAMS).ThrowErr(env);
317 return nullptr;
318 }
319 shared_ptr<PolicyErrorArgs> arg = make_shared<PolicyErrorArgs>();
320 if (arg == nullptr) {
321 LOGE("Make_shared is failed");
322 std::tuple<uint32_t, std::string> errInfo =
323 std::make_tuple(E_UNKNOWN_ERROR, "Out of memory, execute make_shared function failed");
324 ErrParam errorParam = [errInfo]() { return errInfo; };
325 NError(errorParam).ThrowErr(env);
326 return nullptr;
327 }
328 auto cbExec = [uriPolicies, arg]() -> NError {
329 arg->errNo = FilePermission::ActivatePermission(uriPolicies, arg->errorResults);
330 return NError(arg->errNo);
331 };
332 auto cbCompl = [arg](napi_env env, NError err) -> NVal {
333 if (err) {
334 if (arg->errNo == EPERM) {
335 napi_value data = err.GetNapiErr(env);
336 napi_set_named_property(env, data, FILEIO_TAG_ERR_DATA.c_str(), GetErrData(env, arg->errorResults));
337 return NVal(env, data);
338 }
339 return {env, err.GetNapiErr(env)};
340 }
341 return NVal::CreateUndefined(env);
342 };
343 const string procedureName = "activate_permission";
344 NVal thisVar(env, funcArg.GetThisVar());
345 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
346 }
347
DeactivatePermission(napi_env env,napi_callback_info info)348 napi_value DeactivatePermission(napi_env env, napi_callback_info info)
349 {
350 NFuncArg funcArg(env, info);
351 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
352 LOGE("DeactivatePermission Number of arguments unmatched");
353 NError(E_PARAMS).ThrowErr(env);
354 return nullptr;
355 }
356 std::vector<UriPolicyInfo> uriPolicies;
357 if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
358 NError(E_PARAMS).ThrowErr(env);
359 return nullptr;
360 }
361 shared_ptr<PolicyErrorArgs> arg = make_shared<PolicyErrorArgs>();
362 if (arg == nullptr) {
363 LOGE("Make_shared is failed");
364 std::tuple<uint32_t, std::string> errInfo =
365 std::make_tuple(E_UNKNOWN_ERROR, "Out of memory, execute make_shared function failed");
366 ErrParam errorParam = [errInfo]() { return errInfo; };
367 NError(errorParam).ThrowErr(env);
368 return nullptr;
369 }
370 auto cbExec = [uriPolicies, arg]() -> NError {
371 arg->errNo = FilePermission::DeactivatePermission(uriPolicies, arg->errorResults);
372 return NError(arg->errNo);
373 };
374 auto cbCompl = [arg](napi_env env, NError err) -> NVal {
375 if (err) {
376 if (arg->errNo == EPERM) {
377 napi_value data = err.GetNapiErr(env);
378 napi_set_named_property(env, data, FILEIO_TAG_ERR_DATA.c_str(), GetErrData(env, arg->errorResults));
379 return NVal(env, data);
380 }
381 return {env, err.GetNapiErr(env)};
382 }
383 return NVal::CreateUndefined(env);
384 };
385 const string procedureName = "deactivate_permission";
386 NVal thisVar(env, funcArg.GetThisVar());
387 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
388 }
389
CheckPersistentPermission(napi_env env,napi_callback_info info)390 napi_value CheckPersistentPermission(napi_env env, napi_callback_info info)
391 {
392 NFuncArg funcArg(env, info);
393 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
394 LOGE("ActivatePermission Number of arguments unmatched");
395 NError(E_PARAMS).ThrowErr(env);
396 return nullptr;
397 }
398 std::vector<UriPolicyInfo> uriPolicies;
399 if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
400 NError(E_PARAMS).ThrowErr(env);
401 return nullptr;
402 }
403 shared_ptr<PolicyInfoResultArgs> arg = make_shared<PolicyInfoResultArgs>();
404 if (arg == nullptr) {
405 LOGE("Make_shared is failed");
406 std::tuple<uint32_t, std::string> errInfo =
407 std::make_tuple(E_UNKNOWN_ERROR, "Out of memory, execute make_shared function failed");
408 ErrParam errorParam = [errInfo]() { return errInfo; };
409 NError(errorParam).ThrowErr(env);
410 return nullptr;
411 }
412 auto cbExec = [uriPolicies, arg]() -> NError {
413 arg->errNo = FilePermission::CheckPersistentPermission(uriPolicies, arg->resultData);
414 return NError(arg->errNo);
415 };
416 auto cbCompl = [arg](napi_env env, NError err) -> NVal {
417 if (arg->errNo != 0) {
418 return {env, err.GetNapiErr(env)};
419 }
420 return {env, GetResultData(env, arg->resultData)};
421 };
422 const string procedureName = "check_persist_permission";
423 NVal thisVar(env, funcArg.GetThisVar());
424 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
425 }
426
CheckTokenIdPermission(uint32_t tokenCaller,const string & permission)427 static bool CheckTokenIdPermission(uint32_t tokenCaller, const string &permission)
428 {
429 return AccessTokenKit::VerifyAccessToken(tokenCaller, permission) == PermissionState::PERMISSION_GRANTED;
430 }
431
CheckArgs(napi_env env,napi_callback_info info,NFuncArg & funcArg)432 static bool CheckArgs(napi_env env, napi_callback_info info, NFuncArg &funcArg)
433 {
434 if (!funcArg.InitArgs(NARG_CNT::THREE)) {
435 LOGE("ActivatePermission Number of arguments unmatched");
436 return false;
437 }
438
439 auto [succTokenId, tokenId] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
440 if (!succTokenId || tokenId == 0) {
441 LOGE("Failed to get tokenid or tokenid is 0");
442 return false;
443 }
444
445 auto [succPolicyType, policyType] = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32();
446 if (!succPolicyType || policyType < TEMPORARY_TYPE || policyType > PERSISTENT_TYPE) {
447 LOGE("Failed to get policy type or policy type is invalid");
448 return false;
449 }
450 return true;
451 }
452
CheckPathPermission(napi_env env,napi_callback_info info)453 napi_value CheckPathPermission(napi_env env, napi_callback_info info)
454 {
455 if (!IsSystemApp()) {
456 LOGE("FileShare::CheckPathPermission is not System App!");
457 NError(E_PERMISSION_SYS).ThrowErr(env);
458 return nullptr;
459 }
460
461 NFuncArg funcArg(env, info);
462 if (!CheckArgs(env, info, funcArg)) {
463 NError(E_PARAMS).ThrowErr(env);
464 return nullptr;
465 }
466
467 auto [succTokenId, tokenId] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
468
469 uint32_t callerTokenId = OHOS::IPCSkeleton::GetCallingTokenID();
470 if (tokenId != static_cast<int32_t>(callerTokenId)) {
471 if (!CheckTokenIdPermission(callerTokenId, "ohos.permission.CHECK_SANDBOX_POLICY")) {
472 NError(E_PERMISSION).ThrowErr(env);
473 return nullptr;
474 }
475 }
476
477 std::vector<PathPolicyInfo> pathPolicies;
478 if (GetPathPoliciesArg(env, funcArg[NARG_POS::SECOND], pathPolicies) != napi_ok) {
479 NError(E_PARAMS).ThrowErr(env);
480 return nullptr;
481 }
482
483 auto [succPolicyType, policyType] = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32();
484
485 LOGI("check permission target:%{public}d type:%{public}d", tokenId, policyType);
486
487 shared_ptr<PolicyInfoResultArgs> arg = make_shared<PolicyInfoResultArgs>();
488 if (arg == nullptr) {
489 LOGE("Make_shared is failed");
490 std::tuple<uint32_t, std::string> errInfo =
491 std::make_tuple(E_UNKNOWN_ERROR, "Out of memory, execute make_shared function failed");
492 ErrParam errorParam = [errInfo]() { return errInfo; };
493 NError(errorParam).ThrowErr(env);
494 return nullptr;
495 }
496 auto cbExec = [tokenId {move(tokenId)}, pathPolicies, policyType {move(policyType)}, arg]() -> NError {
497 arg->errNo = FilePermission::CheckPathPermission(tokenId, pathPolicies, policyType, arg->resultData);
498 return NError(arg->errNo);
499 };
500 auto cbCompl = [arg](napi_env env, NError err) -> NVal {
501 if (arg->errNo != 0) {
502 return {env, err.GetNapiErr(env)};
503 }
504 return {env, GetResultData(env, arg->resultData)};
505 };
506 const string procedureName = "check_path_permission";
507 NVal thisVar(env, funcArg.GetThisVar());
508 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
509 }
510
GrantDecUriPermission(napi_env env,FileManagement::LibN::NFuncArg & funcArg)511 napi_value GrantDecUriPermission(napi_env env, FileManagement::LibN::NFuncArg &funcArg)
512 {
513 LOGI("GrantDecUriPermission");
514 std::vector<UriPolicyInfo> uriPolicies;
515 if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
516 NError(E_PARAMS).ThrowErr(env);
517 return nullptr;
518 }
519
520 auto [succBundleName, bundleName, lenBundleName] = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String();
521 if (!succBundleName) {
522 LOGE("FileShare::GetJSArgs get bundleName parameter failed!");
523 NError(EINVAL).ThrowErr(env);
524 return nullptr;
525 }
526 std::string targetBundleName = string(bundleName.get());
527
528 auto [succAppCloneIndex, appCloneIndex] = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32();
529
530 shared_ptr<PolicyErrorArgs> arg = make_shared<PolicyErrorArgs>();
531 if (arg == nullptr) {
532 LOGE("PolicyInfoResultArgs make_shared is failed");
533 NError(E_NOMEM).ThrowErr(env);
534 return nullptr;
535 }
536 auto cbExec = [uriPolicies, targetBundleName, appCloneIndex {move(appCloneIndex)}, arg]() -> NError {
537 arg->errNo = FilePermission::GrantPermission(uriPolicies, targetBundleName, appCloneIndex, arg->errorResults);
538 return NError(arg->errNo);
539 };
540 auto cbCompl = [arg](napi_env env, NError err) -> NVal {
541 if (err) {
542 if (arg->errNo == EPERM) {
543 napi_value data = err.GetNapiErr(env);
544 napi_set_named_property(env, data, FILEIO_TAG_ERR_DATA.c_str(), GetErrData(env, arg->errorResults));
545 return NVal(env, data);
546 }
547 return {env, err.GetNapiErr(env)};
548 }
549 return NVal::CreateUndefined(env);
550 };
551 const string procedureName = "grant_permission";
552 NVal thisVar(env, funcArg.GetThisVar());
553 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
554 }
555
556 } // namespace ModuleFileShare
557 } // namespace AppFileService
558 } // namespace OHOS
559