• 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 
16 #include "napi_fileaccess_helper.h"
17 
18 #include <cstring>
19 #include <utility>
20 #include <vector>
21 
22 #include "file_access_framework_errno.h"
23 #include "file_access_helper.h"
24 #include "file_info_entity.h"
25 #include "filemgmt_libn.h"
26 #include "hilog_wrapper.h"
27 #include "ifile_access_notify.h"
28 #include "napi_base_context.h"
29 #include "napi_common_fileaccess.h"
30 #include "napi_file_info_exporter.h"
31 #include "napi_notify_callback.h"
32 #include "napi_root_iterator_exporter.h"
33 #include "root_iterator_entity.h"
34 #include "securec.h"
35 #include "uri.h"
36 
37 using namespace OHOS::AAFwk;
38 using namespace OHOS::AppExecFwk;
39 using namespace OHOS::FileManagement::LibN;
40 
41 namespace OHOS {
42 namespace FileAccessFwk {
43 namespace {
44     const std::string FILEACCESS_CLASS_NAME = "FileAccessHelper";
45     static napi_ref g_constructorRef = nullptr;
46     constexpr uint32_t INITIAL_REFCOUNT = 1;
47 }
48 
49 std::list<std::shared_ptr<FileAccessHelper>> g_fileAccessHelperList;
50 
FileAccessHelperConstructor(napi_env env,napi_callback_info info)51 static napi_value FileAccessHelperConstructor(napi_env env, napi_callback_info info)
52 {
53     NFuncArg funcArg(env, info);
54     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
55         NError(EINVAL).ThrowErr(env);
56         return nullptr;
57     }
58 
59     napi_value thisVar = funcArg.GetThisVar();
60     std::pair<std::shared_ptr<FileAccessHelper>, int> createResult{nullptr, ERR_OK};
61     bool isStageMode = false;
62     napi_status status = AbilityRuntime::IsStageContext(env, funcArg.GetArg(PARAM0), isStageMode);
63     if (status != napi_ok || !isStageMode) {
64         HILOG_INFO("No support FA Model");
65         NError(EINVAL).ThrowErr(env);
66         return nullptr;
67     }
68 
69     auto context = OHOS::AbilityRuntime::GetStageModeContext(env, funcArg.GetArg(PARAM0));
70     if (context == nullptr) {
71         HILOG_ERROR("FileAccessHelperConstructor: failed to get native context");
72         NError(E_GETRESULT).ThrowErr(env);
73         return nullptr;
74     }
75 
76     if (funcArg.GetArgc() == NARG_CNT::ONE) {
77         createResult = FileAccessHelper::Creator(context);
78     } else if (funcArg.GetArgc() == NARG_CNT::TWO) {
79         std::vector<AAFwk::Want> wants;
80         bool suss = UnwrapArrayWantFromJS(env, funcArg.GetArg(PARAM1), wants);
81         if (!suss) {
82             HILOG_ERROR("UnwrapArrayWantFromJS failed to get native wants");
83             NError(E_GETRESULT).ThrowErr(env);
84             return nullptr;
85         }
86         createResult = FileAccessHelper::Creator(context, wants);
87     }
88     if (createResult.first == nullptr || createResult.second != ERR_OK) {
89         HILOG_ERROR("FileAccessHelperConstructor: Creator failed ret=%{public}d", createResult.second);
90         NError(createResult.second).ThrowErr(env);
91         return nullptr;
92     }
93     g_fileAccessHelperList.emplace_back(createResult.first);
94 
95     auto finalize = [](napi_env env, void *data, void *hint) {
96         FileAccessHelper *objectInfo = static_cast<FileAccessHelper *>(data);
97         if (objectInfo != nullptr) {
98             objectInfo->Release();
99             g_fileAccessHelperList.remove_if([objectInfo](const std::shared_ptr<FileAccessHelper> &fileAccessHelper) {
100                     return objectInfo == fileAccessHelper.get();
101                 });
102             objectInfo = nullptr;
103         }
104     };
105     if (napi_wrap(env, thisVar, createResult.first.get(), finalize, nullptr, nullptr) != napi_ok) {
106         finalize(env, createResult.first.get(), nullptr);
107         NError(E_GETRESULT).ThrowErr(env);
108         return nullptr;
109     }
110     return thisVar;
111 }
112 
AcquireFileAccessHelperWrap(napi_env env,napi_callback_info info)113 napi_value AcquireFileAccessHelperWrap(napi_env env, napi_callback_info info)
114 {
115     NFuncArg funcArg(env, info);
116     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
117         NError(EINVAL).ThrowErr(env);
118         return nullptr;
119     }
120 
121     napi_value result = nullptr;
122     napi_value cons = nullptr;
123     if (funcArg.GetArgc() == NARG_CNT::ONE) {
124         size_t requireArgc = ARGS_ONE;
125         size_t argc = ARGS_ONE;
126         napi_value args[ARGS_ONE] = {nullptr};
127         if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
128             return nullptr;
129         }
130 
131         if (argc > requireArgc || napi_get_reference_value(env, g_constructorRef, &cons) != napi_ok) {
132             HILOG_ERROR("Wrong argument count%{public}zu. or g_constructorRef reference is fail", argc);
133             return nullptr;
134         }
135 
136         if (napi_new_instance(env, cons, ARGS_ONE, args, &result) != napi_ok) {
137             return nullptr;
138         }
139     } else if (funcArg.GetArgc() == NARG_CNT::TWO) {
140         size_t requireArgc = ARGS_TWO;
141         size_t argc = ARGS_TWO;
142         napi_value args[ARGS_TWO] = {nullptr};
143         if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
144             return nullptr;
145         }
146 
147         if (argc > requireArgc || napi_get_reference_value(env, g_constructorRef, &cons) != napi_ok) {
148             HILOG_ERROR("Wrong argument count%{public}zu. or g_constructorRef reference is fail", argc);
149             return nullptr;
150         }
151 
152         if (napi_new_instance(env, cons, ARGS_TWO, args, &result) != napi_ok) {
153             return nullptr;
154         }
155     }
156 
157     if (!IsTypeForNapiValue(env, result, napi_object)) {
158         HILOG_ERROR("IsTypeForNapiValue isn`t object");
159         return nullptr;
160     }
161 
162     FileAccessHelper *fileAccessHelper = nullptr;
163     if (napi_unwrap(env, result, (void **)&fileAccessHelper) != napi_ok) {
164         HILOG_ERROR("Faild to get fileAccessHelper");
165         return nullptr;
166     }
167 
168     if (fileAccessHelper == nullptr) {
169         HILOG_ERROR("fileAccessHelper is nullptr");
170         return nullptr;
171     }
172 
173     return result;
174 }
175 
NAPI_CreateFileAccessHelper(napi_env env,napi_callback_info info)176 napi_value NAPI_CreateFileAccessHelper(napi_env env, napi_callback_info info)
177 {
178     napi_value ret = AcquireFileAccessHelperWrap(env, info);
179     if (ret == nullptr) {
180         ret = WrapVoidToJS(env);
181     }
182     return ret;
183 }
184 
NAPI_GetFileAccessAbilityInfo(napi_env env,napi_callback_info info)185 napi_value NAPI_GetFileAccessAbilityInfo(napi_env env, napi_callback_info info)
186 {
187     NFuncArg funcArg(env, info);
188     if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
189         NError(EINVAL).ThrowErr(env);
190         return nullptr;
191     }
192 
193     auto result = std::make_shared<std::vector<AAFwk::Want>>();
194     if (result == nullptr) {
195         NError(E_GETRESULT).ThrowErr(env);
196         return nullptr;
197     }
198 
199     auto cbExec = [result]() -> NError {
200         int ret = FileAccessHelper::GetRegisteredFileAccessExtAbilityInfo(*result);
201         return NError(ret);
202     };
203     auto cbComplete = [result](napi_env env, NError err) -> NVal {
204         if (err) {
205             return { env, err.GetNapiErr(env) };
206         }
207         napi_value jsArray = WrapArrayWantToJS(env, *result);
208         return {env, jsArray};
209     };
210     const std::string procedureName = "getFileAccessAbilityInfo";
211     NVal thisVar(env, funcArg.GetThisVar());
212     if (funcArg.GetArgc() == NARG_CNT::ZERO) {
213         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
214     }
215     NVal cb(env, funcArg[NARG_POS::FIRST]);
216     if (!cb.TypeIs(napi_function)) {
217         NError(EINVAL).ThrowErr(env);
218         return nullptr;
219     }
220     return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
221 }
222 
FileAccessHelperInit(napi_env env,napi_value exports)223 napi_value FileAccessHelperInit(napi_env env, napi_value exports)
224 {
225     napi_property_descriptor properties[] = {
226         DECLARE_NAPI_FUNCTION("openFile", NAPI_OpenFile),
227         DECLARE_NAPI_FUNCTION("mkDir", NAPI_Mkdir),
228         DECLARE_NAPI_FUNCTION("createFile", NAPI_CreateFile),
229         DECLARE_NAPI_FUNCTION("delete", NAPI_Delete),
230         DECLARE_NAPI_FUNCTION("move", NAPI_Move),
231         DECLARE_NAPI_FUNCTION("rename", NAPI_Rename),
232         DECLARE_NAPI_FUNCTION("getRoots", NAPI_GetRoots),
233         DECLARE_NAPI_FUNCTION("access", NAPI_Access),
234         DECLARE_NAPI_FUNCTION("uriToFileInfo", NAPI_UriToFileInfo),
235         DECLARE_NAPI_FUNCTION("on", NAPI_On),
236         DECLARE_NAPI_FUNCTION("off", NAPI_Off)
237     };
238     napi_value cons = nullptr;
239     NAPI_CALL(env,
240         napi_define_class(env,
241             FILEACCESS_CLASS_NAME.c_str(),
242             NAPI_AUTO_LENGTH,
243             FileAccessHelperConstructor,
244             nullptr,
245             sizeof(properties) / sizeof(*properties),
246             properties,
247             &cons));
248     g_fileAccessHelperList.clear();
249     NAPI_CALL(env, napi_create_reference(env, cons, INITIAL_REFCOUNT, &g_constructorRef));
250     NAPI_CALL(env, napi_set_named_property(env, exports, FILEACCESS_CLASS_NAME.c_str(), cons));
251 
252     napi_property_descriptor export_properties[] = {
253         DECLARE_NAPI_FUNCTION("createFileAccessHelper", NAPI_CreateFileAccessHelper),
254         DECLARE_NAPI_FUNCTION("getFileAccessAbilityInfo", NAPI_GetFileAccessAbilityInfo),
255     };
256     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(export_properties) / sizeof(export_properties[0]),
257         export_properties));
258     return exports;
259 }
260 
InitOpenFlags(napi_env env,napi_value exports)261 void InitOpenFlags(napi_env env, napi_value exports)
262 {
263     char propertyName[] = "OPENFLAGS";
264     napi_property_descriptor desc[] = {
265         DECLARE_NAPI_STATIC_PROPERTY("READ", NVal::CreateInt32(env, READ).val_),
266         DECLARE_NAPI_STATIC_PROPERTY("WRITE", NVal::CreateInt32(env, WRITE).val_),
267         DECLARE_NAPI_STATIC_PROPERTY("WRITE_READ", NVal::CreateInt32(env, WRITE_READ).val_)
268     };
269     napi_value obj = nullptr;
270     napi_create_object(env, &obj);
271     napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
272     napi_set_named_property(env, exports, propertyName, obj);
273 }
274 
GetFileAccessHelper(napi_env env,napi_value thisVar)275 static FileAccessHelper *GetFileAccessHelper(napi_env env, napi_value thisVar)
276 {
277     if (thisVar == nullptr) {
278         NError(EINVAL).ThrowErr(env);
279         return nullptr;
280     }
281 
282     FileAccessHelper *fileAccessHelper = nullptr;
283     if (napi_unwrap(env, thisVar, (void **)&fileAccessHelper) != napi_ok) {
284         NError(E_GETRESULT).ThrowErr(env);
285         return nullptr;
286     }
287 
288     if (fileAccessHelper == nullptr) {
289         NError(E_GETRESULT).ThrowErr(env);
290         return nullptr;
291     }
292     return fileAccessHelper;
293 }
294 
GetReadArg(napi_env env,napi_value sourceFile,napi_value targetParent)295 static std::tuple<bool, std::unique_ptr<char[]>, std::unique_ptr<char[]>> GetReadArg(napi_env env,
296                                                                                      napi_value sourceFile,
297                                                                                      napi_value targetParent)
298 {
299     bool succ = false;
300     std::unique_ptr<char[]> uri = nullptr;
301     std::unique_ptr<char[]> name = nullptr;
302     std::tie(succ, uri, std::ignore) = NVal(env, sourceFile).ToUTF8String();
303     if (!succ) {
304         NError(EINVAL).ThrowErr(env);
305         return { false, std::move(uri), std::move(name) };
306     }
307 
308     std::tie(succ, name, std::ignore) = NVal(env, targetParent).ToUTF8String();
309     if (!succ) {
310         NError(EINVAL).ThrowErr(env);
311         return { false, std::move(uri), std::move(name) };
312     }
313 
314     return { true, std::move(uri), std::move(name) };
315 }
316 
NAPI_OpenFile(napi_env env,napi_callback_info info)317 napi_value NAPI_OpenFile(napi_env env, napi_callback_info info)
318 {
319     NFuncArg funcArg(env, info);
320     if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
321         NError(EINVAL).ThrowErr(env);
322         return nullptr;
323     }
324 
325     bool succ = false;
326     std::unique_ptr<char[]> uri;
327     std::tie(succ, uri, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
328     if (!succ) {
329         NError(EINVAL).ThrowErr(env);
330         return nullptr;
331     }
332 
333     int flags;
334     std::tie(succ, flags) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
335     if (!succ) {
336         NError(EINVAL).ThrowErr(env);
337         return nullptr;
338     }
339 
340     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
341     if (fileAccessHelper == nullptr) {
342         return nullptr;
343     }
344 
345     auto result = std::make_shared<int>();
346     if (result == nullptr) {
347         NError(E_GETRESULT).ThrowErr(env);
348         return nullptr;
349     }
350 
351     string uriString(uri.get());
352     auto cbExec = [uriString, flags, result, fileAccessHelper]() -> NError {
353         OHOS::Uri uri(uriString);
354         int ret = fileAccessHelper->OpenFile(uri, flags, *result);
355         return NError(ret);
356     };
357     auto cbComplete = [result](napi_env env, NError err) -> NVal {
358         if (err) {
359             return { env, err.GetNapiErr(env) };
360         }
361         return { NVal::CreateInt32(env, *result) };
362     };
363 
364     const std::string procedureName = "openFile";
365     NVal thisVar(env, funcArg.GetThisVar());
366     if (funcArg.GetArgc() == NARG_CNT::TWO) {
367         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
368     }
369 
370     NVal cb(env, funcArg[NARG_POS::THIRD]);
371     if (!cb.TypeIs(napi_function)) {
372         NError(EINVAL).ThrowErr(env);
373         return nullptr;
374     }
375     return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
376 }
377 
NAPI_CreateFile(napi_env env,napi_callback_info info)378 napi_value NAPI_CreateFile(napi_env env, napi_callback_info info)
379 {
380     NFuncArg funcArg(env, info);
381     if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
382         NError(EINVAL).ThrowErr(env);
383         return nullptr;
384     }
385 
386     bool succ = false;
387     std::unique_ptr<char[]> uri;
388     std::unique_ptr<char[]> displayName;
389     std::tie(succ, uri, displayName) = GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
390     if (!succ) {
391         return nullptr;
392     }
393 
394     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
395     if (fileAccessHelper == nullptr) {
396         return nullptr;
397     }
398 
399     auto result = std::make_shared<string>();
400     if (result == nullptr) {
401         NError(E_GETRESULT).ThrowErr(env);
402         return nullptr;
403     }
404 
405     string uriString(uri.get());
406     string name(displayName.get());
407     auto cbExec = [uriString, name, result, fileAccessHelper]() -> NError {
408         OHOS::Uri uri(uriString);
409         std::string newFile = "";
410         OHOS::Uri newFileUri(newFile);
411         int ret = fileAccessHelper->CreateFile(uri, name, newFileUri);
412         *result = newFileUri.ToString();
413         return NError(ret);
414     };
415     auto cbComplete = [result](napi_env env, NError err) -> NVal {
416         if (err) {
417             return { env, err.GetNapiErr(env) };
418         }
419         return { NVal::CreateUTF8String(env, *result) };
420     };
421     const std::string procedureName = "createFile";
422     NVal thisVar(env, funcArg.GetThisVar());
423     if (funcArg.GetArgc() == NARG_CNT::TWO) {
424         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
425     }
426 
427     NVal cb(env, funcArg[NARG_POS::THIRD]);
428     if (!cb.TypeIs(napi_function)) {
429         NError(EINVAL).ThrowErr(env);
430         return nullptr;
431     }
432     return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
433 }
434 
NAPI_Mkdir(napi_env env,napi_callback_info info)435 napi_value NAPI_Mkdir(napi_env env, napi_callback_info info)
436 {
437     NFuncArg funcArg(env, info);
438     if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
439         NError(EINVAL).ThrowErr(env);
440         return nullptr;
441     }
442 
443     bool succ = false;
444     std::unique_ptr<char[]> uri;
445     std::unique_ptr<char[]> displayName;
446     std::tie(succ, uri, displayName) = GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
447     if (!succ) {
448         return nullptr;
449     }
450 
451     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
452     if (fileAccessHelper == nullptr) {
453         return nullptr;
454     }
455 
456     auto result = std::make_shared<string>();
457     if (result == nullptr) {
458         NError(E_GETRESULT).ThrowErr(env);
459         return nullptr;
460     }
461 
462     string uriString(uri.get());
463     string name(displayName.get());
464     auto cbExec = [uriString, name, result, fileAccessHelper]() -> NError {
465         OHOS::Uri uri(uriString);
466         std::string newFile = "";
467         OHOS::Uri newFileUri(newFile);
468         int ret = fileAccessHelper->Mkdir(uri, name, newFileUri);
469         *result = newFileUri.ToString();
470         return NError(ret);
471     };
472     auto cbComplete = [result](napi_env env, NError err) -> NVal {
473         if (err) {
474             return { env, err.GetNapiErr(env) };
475         }
476         return { NVal::CreateUTF8String(env, *result) };
477     };
478     const std::string procedureName = "mkdir";
479     NVal thisVar(env, funcArg.GetThisVar());
480     if (funcArg.GetArgc() == NARG_CNT::TWO) {
481         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
482     }
483 
484     NVal cb(env, funcArg[NARG_POS::THIRD]);
485     if (!cb.TypeIs(napi_function)) {
486         NError(EINVAL).ThrowErr(env);
487         return nullptr;
488     }
489     return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
490 }
491 
NAPI_Delete(napi_env env,napi_callback_info info)492 napi_value NAPI_Delete(napi_env env, napi_callback_info info)
493 {
494     NFuncArg funcArg(env, info);
495     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
496         NError(EINVAL).ThrowErr(env);
497         return nullptr;
498     }
499 
500     bool succ = false;
501     std::unique_ptr<char[]> uri;
502     std::tie(succ, uri, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
503     if (!succ) {
504         NError(EINVAL).ThrowErr(env);
505         return nullptr;
506     }
507 
508     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
509     if (fileAccessHelper == nullptr) {
510         return nullptr;
511     }
512 
513     auto result = std::make_shared<int>();
514     if (result == nullptr) {
515         NError(E_GETRESULT).ThrowErr(env);
516         return nullptr;
517     }
518 
519     string uriString(uri.get());
520     auto cbExec = [uriString, result, fileAccessHelper]() -> NError {
521         OHOS::Uri uri(uriString);
522         *result = fileAccessHelper->Delete(uri);
523         return NError(*result);
524     };
525     auto cbComplete = [result](napi_env env, NError err) -> NVal {
526         if (err) {
527             return { env, err.GetNapiErr(env) };
528         }
529         return { NVal::CreateInt32(env, ERRNO_NOERR) };
530     };
531 
532     const std::string procedureName = "delete";
533     NVal thisVar(env, funcArg.GetThisVar());
534     if (funcArg.GetArgc() == NARG_CNT::ONE) {
535         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
536     }
537 
538     NVal cb(env, funcArg[NARG_POS::SECOND]);
539     if (!cb.TypeIs(napi_function)) {
540         NError(EINVAL).ThrowErr(env);
541         return nullptr;
542     }
543     return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
544 }
545 
NAPI_Move(napi_env env,napi_callback_info info)546 napi_value NAPI_Move(napi_env env, napi_callback_info info)
547 {
548     NFuncArg funcArg(env, info);
549     if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
550         NError(EINVAL).ThrowErr(env);
551         return nullptr;
552     }
553 
554     bool succ = false;
555     std::unique_ptr<char[]> sourceFile;
556     std::unique_ptr<char[]> targetParent;
557     std::tie(succ, sourceFile, targetParent) = GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
558     if (!succ) {
559         return nullptr;
560     }
561 
562     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
563     if (fileAccessHelper == nullptr) {
564         return nullptr;
565     }
566 
567     auto result = std::make_shared<string>();
568     if (result == nullptr) {
569         NError(E_GETRESULT).ThrowErr(env);
570         return nullptr;
571     }
572 
573     string sourceFileString(sourceFile.get());
574     string targetParentString(targetParent.get());
575     auto cbExec = [sourceFileString, targetParentString, result, fileAccessHelper]() -> NError {
576         OHOS::Uri uri(sourceFileString);
577         OHOS::Uri targetParentUri(targetParentString);
578         std::string newFile = "";
579         OHOS::Uri newFileUri(newFile);
580         int ret = fileAccessHelper->Move(uri, targetParentUri, newFileUri);
581         *result = newFileUri.ToString();
582         return NError(ret);
583     };
584     auto cbComplete = [result](napi_env env, NError err) -> NVal {
585         if (err) {
586             return { env, err.GetNapiErr(env) };
587         }
588         return { NVal::CreateUTF8String(env, *result) };
589     };
590     const std::string procedureName = "move";
591     NVal thisVar(env, funcArg.GetThisVar());
592     if (funcArg.GetArgc() == NARG_CNT::TWO) {
593         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
594     }
595 
596     NVal cb(env, funcArg[NARG_POS::THIRD]);
597     if (!cb.TypeIs(napi_function)) {
598         NError(EINVAL).ThrowErr(env);
599         return nullptr;
600     }
601     return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
602 }
603 
NAPI_Rename(napi_env env,napi_callback_info info)604 napi_value NAPI_Rename(napi_env env, napi_callback_info info)
605 {
606     NFuncArg funcArg(env, info);
607     if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
608         NError(EINVAL).ThrowErr(env);
609         return nullptr;
610     }
611 
612     bool succ = false;
613     std::unique_ptr<char[]> uri;
614     std::unique_ptr<char[]> displayName;
615     std::tie(succ, uri, displayName) = GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
616     if (!succ) {
617         return nullptr;
618     }
619 
620     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
621     if (fileAccessHelper == nullptr) {
622         return nullptr;
623     }
624 
625     auto result = std::make_shared<string>();
626     if (result == nullptr) {
627         NError(E_GETRESULT).ThrowErr(env);
628         return nullptr;
629     }
630 
631     string uriString(uri.get());
632     string name(displayName.get());
633     auto cbExec = [uriString, name, result, fileAccessHelper]() -> NError {
634         OHOS::Uri uri(uriString);
635         std::string newFile = "";
636         OHOS::Uri newFileUri(newFile);
637         int ret = fileAccessHelper->Rename(uri, name, newFileUri);
638         *result = newFileUri.ToString();
639         return NError(ret);
640     };
641     auto cbComplete = [result](napi_env env, NError err) -> NVal {
642         if (err) {
643             return { env, err.GetNapiErr(env) };
644         }
645         return { NVal::CreateUTF8String(env, *result) };
646     };
647     const std::string procedureName = "rename";
648     NVal thisVar(env, funcArg.GetThisVar());
649     if (funcArg.GetArgc() == NARG_CNT::TWO) {
650         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
651     }
652 
653     NVal cb(env, funcArg[NARG_POS::THIRD]);
654     if (!cb.TypeIs(napi_function)) {
655         NError(EINVAL).ThrowErr(env);
656         return nullptr;
657     }
658     return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
659 }
660 
MakeGetRootsResult(napi_env & env,FileAccessHelper * helper,std::vector<RootInfo> & rootInfoVec,NVal & nVal)661 static int MakeGetRootsResult(napi_env &env, FileAccessHelper *helper, std::vector<RootInfo> &rootInfoVec, NVal &nVal)
662 {
663     auto objRootIterator = NClass::InstantiateClass(env, NapiRootIteratorExporter::className_, {});
664     if (objRootIterator == nullptr) {
665         HILOG_INFO("Cannot instantiate class NapiRootIteratorExporter");
666         return E_GETRESULT;
667     }
668 
669     auto rootIteratorEntity = NClass::GetEntityOf<RootIteratorEntity>(env, objRootIterator);
670     if (rootIteratorEntity == nullptr) {
671         HILOG_INFO("Cannot get the entity of RootIteratorEntity");
672         return E_GETRESULT;
673     }
674 
675     std::lock_guard<std::mutex> lock(rootIteratorEntity->entityOperateMutex);
676     rootIteratorEntity->fileAccessHelper = helper;
677     rootIteratorEntity->devVec = std::move(rootInfoVec);
678     rootIteratorEntity->pos = 0;
679     nVal = { env, objRootIterator };
680 
681     return ERR_OK;
682 }
683 
NAPI_GetRoots(napi_env env,napi_callback_info info)684 napi_value NAPI_GetRoots(napi_env env, napi_callback_info info)
685 {
686     NFuncArg funcArg(env, info);
687     if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
688         NError(EINVAL).ThrowErr(env);
689         return nullptr;
690     }
691 
692     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
693     if (fileAccessHelper == nullptr) {
694         NError(E_GETRESULT).ThrowErr(env);
695         return nullptr;
696     }
697 
698     auto result = std::make_shared<std::vector<RootInfo>>();
699     if (result == nullptr) {
700         NError(E_GETRESULT).ThrowErr(env);
701         return nullptr;
702     }
703 
704     auto cbExec = [result, fileAccessHelper]() -> NError {
705         int ret = fileAccessHelper->GetRoots(*result);
706         return NError(ret);
707     };
708     auto cbComplete = [fileAccessHelper, result](napi_env env, NError err) -> NVal {
709         if (err) {
710             return { env, err.GetNapiErr(env) };
711         }
712 
713         NVal nVal;
714         int ret = MakeGetRootsResult(env, fileAccessHelper, *result, nVal);
715         if (ret != ERR_OK) {
716             return { env, NError([ret]() -> std::tuple<uint32_t, std::string> {
717                 return { ret, "Make GetRoots Result fail" };
718             }).GetNapiErr(env) };
719         }
720 
721         return nVal;
722     };
723 
724     const std::string procedureName = "getRoots";
725     NVal thisVar(env, funcArg.GetThisVar());
726     if (funcArg.GetArgc() == NARG_CNT::ZERO) {
727         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
728     }
729 
730     NVal cb(env, funcArg[NARG_POS::FIRST]);
731     if (!cb.TypeIs(napi_function)) {
732         NError(EINVAL).ThrowErr(env);
733         return nullptr;
734     }
735     return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
736 }
737 
NAPI_Access(napi_env env,napi_callback_info info)738 napi_value NAPI_Access(napi_env env, napi_callback_info info)
739 {
740     NFuncArg funcArg(env, info);
741     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
742         NError(EINVAL).ThrowErr(env);
743         return nullptr;
744     }
745 
746     bool succ = false;
747     std::unique_ptr<char[]> uri;
748     std::tie(succ, uri, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
749     if (!succ) {
750         NError(EINVAL).ThrowErr(env);
751         return nullptr;
752     }
753 
754     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
755     if (fileAccessHelper == nullptr) {
756         return nullptr;
757     }
758 
759     auto result = std::make_shared<bool>();
760     string uriString(uri.get());
761     auto cbExec = [uriString, result, fileAccessHelper]() -> NError {
762         OHOS::Uri uri(uriString);
763         bool isExist = false;
764         int ret = fileAccessHelper->Access(uri, isExist);
765         *result = isExist;
766         return NError(ret);
767     };
768     auto cbComplete = [result](napi_env env, NError err) -> NVal {
769         if (err) {
770             return { env, err.GetNapiErr(env) };
771         }
772         return { NVal::CreateBool(env, *result) };
773     };
774 
775     const std::string procedureName = "access";
776     NVal thisVar(env, funcArg.GetThisVar());
777     if (funcArg.GetArgc() == NARG_CNT::ONE) {
778         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
779     }
780     NVal cb(env, funcArg[NARG_POS::SECOND]);
781     if (!cb.TypeIs(napi_function)) {
782         NError(EINVAL).ThrowErr(env);
783         return nullptr;
784     }
785     return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
786 }
787 
MakeFileInfoResult(napi_env & env,FileAccessHelper * helper,FileInfo & fileinfo,NVal & nVal)788 static int MakeFileInfoResult(napi_env &env, FileAccessHelper *helper, FileInfo &fileinfo, NVal &nVal)
789 {
790     auto objFileInfo = NClass::InstantiateClass(env, NapiFileInfoExporter::className_, {});
791     if (objFileInfo == nullptr) {
792         HILOG_INFO("Cannot instantiate class NapiFileInfoExporter");
793         return E_GETRESULT;
794     }
795 
796     auto fileInfoEntity = NClass::GetEntityOf<FileInfoEntity>(env, objFileInfo);
797     if (fileInfoEntity == nullptr) {
798         HILOG_INFO("Cannot get the entity of fileInfoEntity");
799         return E_GETRESULT;
800     }
801     fileInfoEntity->fileAccessHelper = helper;
802     fileInfoEntity->fileInfo = std::move(fileinfo);
803     nVal = { env, objFileInfo };
804 
805     return ERR_OK;
806 }
807 
NAPI_UriToFileInfo(napi_env env,napi_callback_info info)808 napi_value NAPI_UriToFileInfo(napi_env env, napi_callback_info info)
809 {
810     NFuncArg funcArg(env, info);
811     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
812         NError(EINVAL).ThrowErr(env);
813         return nullptr;
814     }
815 
816     bool succ = false;
817     std::unique_ptr<char[]> uri;
818     std::tie(succ, uri, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
819     if (!succ) {
820         NError(EINVAL).ThrowErr(env);
821         return nullptr;
822     }
823 
824     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
825     if (fileAccessHelper == nullptr) {
826         return nullptr;
827     }
828 
829     auto result = std::make_shared<FileInfo>();
830     if (result == nullptr) {
831         NError(E_GETRESULT).ThrowErr(env);
832         return nullptr;
833     }
834 
835     string uriString(uri.get());
836     auto cbExec = [uriString, result, fileAccessHelper]() -> NError {
837         OHOS::Uri uri(uriString);
838         int ret = fileAccessHelper->UriToFileInfo(uri, *result);
839         return NError(ret);
840     };
841     auto cbComplete = [fileAccessHelper, result](napi_env env, NError err) -> NVal {
842         if (err) {
843             return { env, err.GetNapiErr(env) };
844         }
845 
846         NVal nVal;
847         int ret = MakeFileInfoResult(env, fileAccessHelper, *result, nVal);
848         if (ret != ERR_OK) {
849             return { env, NError([ret]() -> std::tuple<uint32_t, std::string> {
850                 return { ret, "Make FileInfo Result fail" };
851             }).GetNapiErr(env) };
852         }
853 
854         return nVal;
855     };
856 
857     const std::string procedureName = "uriToFileInfo";
858     NVal thisVar(env, funcArg.GetThisVar());
859     if (funcArg.GetArgc() == NARG_CNT::ONE) {
860         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
861     }
862     NVal cb(env, funcArg[NARG_POS::SECOND]);
863     if (!cb.TypeIs(napi_function)) {
864         NError(EINVAL).ThrowErr(env);
865         return nullptr;
866     }
867     return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
868 }
869 
NAPI_On(napi_env env,napi_callback_info info)870 napi_value NAPI_On(napi_env env, napi_callback_info info)
871 {
872     NFuncArg funcArg(env, info);
873     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
874         NError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
875         return nullptr;
876     }
877 
878     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
879     if (fileAccessHelper == nullptr) {
880         NError(EINVAL).ThrowErr(env, "Get FileAccessHelper fail");
881         return nullptr;
882     }
883 
884     napi_value napiCallback = funcArg[NARG_POS::FIRST];
885     if (!NVal(env, napiCallback).TypeIs(napi_function)) {
886         NError(EINVAL).ThrowErr(env, "Argument must be function");
887         return nullptr;
888     }
889 
890     std::shared_ptr<INotifyCallback> callback = std::make_shared<NapiNotifyCallback>(env, napiCallback);
891     if (callback == nullptr) {
892         NError(EINVAL).ThrowErr(env, "new NapiNotifyCallback fail.");
893         return nullptr;
894     }
895 
896     auto retCode = fileAccessHelper->On(callback);
897     if (retCode != ERR_OK) {
898         NError(retCode).ThrowErr(env, "FileAccessHelper::On fail.");
899         return nullptr;
900     }
901     return NVal::CreateUndefined(env).val_;
902 }
903 
NAPI_Off(napi_env env,napi_callback_info info)904 napi_value NAPI_Off(napi_env env, napi_callback_info info)
905 {
906     NFuncArg funcArg(env, info);
907     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
908         NError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
909         return nullptr;
910     }
911 
912     FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
913     if (fileAccessHelper == nullptr) {
914         NError(EINVAL).ThrowErr(env, "Get FileAccessHelper fail");
915         return nullptr;
916     }
917 
918     auto retCode = fileAccessHelper->Off();
919     if (retCode != ERR_OK) {
920         NError(retCode).ThrowErr(env, "FileAccessHelper::Off fail.");
921         return nullptr;
922     }
923     return NVal::CreateUndefined(env).val_;
924 }
925 } // namespace FileAccessFwk
926 } // namespace OHOS