• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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 "cloud_file_cache_napi.h"
17 
18 #include <cstddef>
19 #include <memory>
20 #include <mutex>
21 #include <sys/types.h>
22 #include <unordered_set>
23 
24 #include "async_work.h"
25 #include "cloud_sync_manager.h"
26 #include "dfs_error.h"
27 #include "multi_download_progress_napi.h"
28 #include "register_callback_manager_napi.h"
29 #include "utils_log.h"
30 
31 namespace OHOS::FileManagement::CloudSync {
32 using namespace FileManagement::LibN;
33 using namespace std;
34 
35 static const std::unordered_set<int32_t> errForSingleFileSync = { ENOENT, EACCES, EAGAIN,
36     EINTR, ENOSYS, E_ILLEGAL_URI };
37 
StartDownloadInner(const std::string & uri,int32_t fieldKey)38 int32_t CloudFileCacheCallbackImplNapi::StartDownloadInner(const std::string &uri, int32_t fieldKey)
39 {
40     int64_t downloadId = 0;
41     std::lock_guard<std::mutex> lock(downloadInfoMtx_);
42     int32_t ret = CloudSyncManager::GetInstance().StartFileCache({uri}, downloadId, fieldKey, shared_from_this());
43     if (ret != E_OK) {
44         LOGE("Start single download failed! ret = %{public}d", ret);
45         return ret;
46     }
47     downloadInfos_[downloadId] = std::make_shared<SingleProgressNapi>(downloadId);
48     return ret;
49 }
50 
StopDownloadInner(const std::string & uri,bool needClean)51 int32_t CloudFileCacheCallbackImplNapi::StopDownloadInner(const std::string &uri, bool needClean)
52 {
53     auto downloadIdList = GetDownloadIdsByUri(uri);
54     int32_t ret = E_OK;
55     int32_t resErr = E_OK;
56     LOGI("Stop Download downloadId list size: %{public}zu", downloadIdList.size());
57     for (auto taskId : downloadIdList) {
58         resErr = CloudSyncManager::GetInstance().StopFileCache(taskId, needClean);
59         if (resErr != E_OK) {
60             ret = resErr;
61             continue;
62         }
63     }
64     if (ret != E_OK) {
65         LOGE("Stop Download failed! ret = %{public}d", ret);
66     }
67     return ret;
68 }
69 
StartDownloadInner(const std::vector<std::string> & uriVec,int64_t & downloadId,int32_t fieldKey)70 int32_t CloudFileCacheCallbackImplNapi::StartDownloadInner(const std::vector<std::string> &uriVec,
71                                                            int64_t &downloadId,
72                                                            int32_t fieldKey)
73 {
74     std::lock_guard<std::mutex> lock(downloadInfoMtx_);
75     int32_t ret = CloudSyncManager::GetInstance().StartFileCache(uriVec, downloadId, fieldKey, shared_from_this());
76     if (ret != E_OK) {
77         LOGE("Start batch download failed! ret = %{public}d", ret);
78         return ret;
79     }
80     downloadInfos_[downloadId] = std::make_shared<BatchProgressNapi>(downloadId);
81     return ret;
82 }
83 
StopDownloadInner(int64_t downloadId,bool needClean)84 int32_t CloudFileCacheCallbackImplNapi::StopDownloadInner(int64_t downloadId, bool needClean)
85 {
86     int32_t ret = CloudSyncManager::GetInstance().StopFileCache(downloadId, needClean);
87     if (ret != E_OK) {
88         LOGE("Batch stop file cache failed! ret = %{public}d", ret);
89     }
90     return ret;
91 }
92 
Constructor(napi_env env,napi_callback_info info)93 napi_value CloudFileCacheNapi::Constructor(napi_env env, napi_callback_info info)
94 {
95     NFuncArg funcArg(env, info);
96     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
97         LOGE("Start Number of arguments unmatched");
98         NError(JsErrCode::E_INNER_FAILED).ThrowErr(env);
99         return nullptr;
100     }
101 
102     auto fileCacheEntity = make_unique<FileCacheEntity>();
103     if (!NClass::SetEntityFor<FileCacheEntity>(env, funcArg.GetThisVar(), move(fileCacheEntity))) {
104         LOGE("Failed to set file cache entity.");
105         NError(JsErrCode::E_INNER_FAILED).ThrowErr(env);
106         return nullptr;
107     }
108     return funcArg.GetThisVar();
109 }
110 
ToExport(std::vector<napi_property_descriptor> props)111 bool CloudFileCacheNapi::ToExport(std::vector<napi_property_descriptor> props)
112 {
113     std::string className = GetClassName();
114     auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props));
115     if (!succ) {
116         NError(JsErrCode::E_INNER_FAILED).ThrowErr(exports_.env_);
117         LOGE("Failed to define GallerySync class");
118         return false;
119     }
120 
121     succ = NClass::SaveClass(exports_.env_, className, classValue);
122     if (!succ) {
123         NError(JsErrCode::E_INNER_FAILED).ThrowErr(exports_.env_);
124         LOGE("Failed to save GallerySync class");
125         return false;
126     }
127 
128     return exports_.AddProp(className, classValue);
129 }
130 
CleanCloudFileCache(napi_env env,napi_callback_info info)131 napi_value CloudFileCacheNapi::CleanCloudFileCache(napi_env env, napi_callback_info info)
132 {
133     LOGI("CleanCache start");
134     NFuncArg funcArg(env, info);
135 
136     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
137         NError(E_PARAMS).ThrowErr(env);
138         return nullptr;
139     }
140 
141     auto [succ, uri, ignore] = NVal(env, funcArg[(int)NARG_POS::FIRST]).ToUTF8String();
142     if (!succ) {
143         LOGE("Get uri error");
144         NError(EINVAL).ThrowErr(env);
145         return nullptr;
146     }
147 
148     int32_t ret = CloudSyncManager::GetInstance().CleanCache(uri.get());
149     if (ret != E_OK) {
150         NError(Convert2JsErrNum(ret)).ThrowErr(env);
151         return nullptr;
152     }
153     return NVal::CreateUndefined(env).val_;
154 }
155 
GetCleanCacheErrPublic(int32_t result)156 static int32_t GetCleanCacheErrPublic(int32_t result)
157 {
158     LOGE("cleanCache failed, errno : %{public}d", result);
159     if (errForSingleFileSync.find(result) != errForSingleFileSync.end()) {
160         return result;
161     }
162     return E_SERVICE_INNER_ERROR;
163 }
164 
CleanFileCache(napi_env env,napi_callback_info info)165 napi_value CloudFileCacheNapi::CleanFileCache(napi_env env, napi_callback_info info)
166 {
167     LOGI("CleanCache start");
168     NFuncArg funcArg(env, info);
169 
170     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
171         NError(EINVAL).ThrowErr(env);
172         LOGE("Number of arguments unmatched");
173         return nullptr;
174     }
175 
176     auto [succ, uri, ignore] = NVal(env, funcArg[(int)NARG_POS::FIRST]).ToUTF8String();
177     if (!succ) {
178         LOGE("CleanFileCache get uri parameter failed!");
179         NError(EINVAL).ThrowErr(env);
180         return nullptr;
181     }
182 
183     int32_t ret = CloudSyncManager::GetInstance().CleanFileCache(uri.get());
184     if (ret != E_OK) {
185         int32_t err = GetCleanCacheErrPublic(ret);
186         NError(Convert2JsErrNum(err)).ThrowErr(env);
187         LOGE("CleanFileCache failed, ret:%{public}d", err);
188         return nullptr;
189     }
190     return NVal::CreateUndefined(env).val_;
191 }
192 
Export()193 bool CloudFileCacheNapi::Export()
194 {
195     std::vector<napi_property_descriptor> props = {
196         NVal::DeclareNapiFunction("on", CloudFileCacheNapi::On),
197         NVal::DeclareNapiFunction("off", CloudFileCacheNapi::Off),
198         NVal::DeclareNapiFunction("start", CloudFileCacheNapi::StartFileCache),
199         NVal::DeclareNapiFunction("startBatch", CloudFileCacheNapi::StartBatchFileCache),
200         NVal::DeclareNapiFunction("stop", CloudFileCacheNapi::StopFileCache),
201         NVal::DeclareNapiFunction("stopBatch", CloudFileCacheNapi::StopBatchFileCache),
202         NVal::DeclareNapiFunction("cleanCache", CloudFileCacheNapi::CleanCloudFileCache),
203         NVal::DeclareNapiFunction("cleanFileCache", CloudFileCacheNapi::CleanFileCache),
204     };
205 
206     return ToExport(props);
207 }
208 
GetCallbackImpl(napi_env env,NFuncArg & funcArg,const std::string & eventType,bool isInit)209 static std::shared_ptr<CloudFileCacheCallbackImplNapi> GetCallbackImpl(napi_env env, NFuncArg &funcArg,
210     const std::string &eventType, bool isInit)
211 {
212     auto fileCacheEntity = NClass::GetEntityOf<FileCacheEntity>(env, funcArg.GetThisVar());
213     if (!fileCacheEntity) {
214         LOGE("Failed to get file cache entity.");
215         return nullptr;
216     }
217 
218     std::shared_ptr<CloudFileCacheCallbackImplNapi> callbackImpl = nullptr;
219     auto iter = fileCacheEntity->registerMap.find(eventType);
220     if (iter == fileCacheEntity->registerMap.end() || iter->second == nullptr) {
221         if (isInit) {
222             callbackImpl = std::make_shared<CloudFileCacheCallbackImplNapi>(env);
223             fileCacheEntity->registerMap.insert(make_pair(eventType, callbackImpl));
224         }
225     } else {
226         callbackImpl = iter->second;
227     }
228     return callbackImpl;
229 }
230 
ParseUriFromParam(napi_env env,NFuncArg & funcArg)231 static std::tuple<int32_t, std::string> ParseUriFromParam(napi_env env, NFuncArg &funcArg)
232 {
233     auto [succ, uri, size] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
234     if (!succ || size == 0) {
235         LOGE("Parse URI from parameter failed!");
236         return {E_PARAMS, ""};
237     }
238     return {E_OK, string(uri.get())};
239 }
240 
StartFileCache(napi_env env,napi_callback_info info)241 napi_value CloudFileCacheNapi::StartFileCache(napi_env env, napi_callback_info info)
242 {
243     NFuncArg funcArg(env, info);
244     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
245         LOGE("Start Number of arguments unmatched");
246         NError(E_PARAMS).ThrowErr(env);
247         return nullptr;
248     }
249 
250     auto [ret, uri] = ParseUriFromParam(env, funcArg);
251     if (ret != E_OK) {
252         NError(ret).ThrowErr(env);
253         return nullptr;
254     }
255     auto callbackImpl = GetCallbackImpl(env, funcArg, PROGRESS, true);
256     auto cbExec = [uri{uri}, callbackImpl{callbackImpl}]() -> NError {
257         if (callbackImpl == nullptr) {
258             LOGE("Failed to get download callback");
259             return NError(E_PARAMS);
260         }
261         int32_t ret = callbackImpl->StartDownloadInner(uri, FieldKey::FIELDKEY_CONTENT);
262         if (ret != E_OK) {
263             LOGE("Start Download failed! ret = %{public}d", ret);
264             if (ret != E_INVAL_ARG) {
265                 ret = E_BROKEN_IPC;
266             }
267             return NError(Convert2JsErrNum(ret));
268         }
269         return NError(ERRNO_NOERR);
270     };
271 
272     auto cbCompl = [](napi_env env, NError err) -> NVal {
273         if (err) {
274             return {env, err.GetNapiErr(env)};
275         }
276         return NVal::CreateUndefined(env);
277     };
278 
279     string procedureName = "cloudFileCache";
280     auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, static_cast<size_t>(NARG_CNT::TWO));
281     return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbCompl).val_;
282 }
283 
GetCleanFlagForStop(napi_env env,NFuncArg & funcArg)284 static tuple<int32_t, bool, bool> GetCleanFlagForStop(napi_env env, NFuncArg &funcArg)
285 {
286     bool succ = true;
287     bool needClean = false;
288     size_t maxArgSize = static_cast<size_t>(NARG_CNT::TWO);
289     if (funcArg.GetArgc() >= NARG_CNT::TWO) {
290         NVal option(env, funcArg[NARG_POS::SECOND]);
291         if (!option.TypeIs(napi_function)) {
292             tie(succ, needClean) = option.ToBool();
293             maxArgSize = static_cast<size_t>(NARG_CNT::THREE);
294         }
295         if (!succ) {
296             LOGE("Failed to get clean flag!");
297             return {EINVAL, false, false};
298         }
299     }
300     return {E_OK, needClean, maxArgSize};
301 }
302 
StopFileCache(napi_env env,napi_callback_info info)303 napi_value CloudFileCacheNapi::StopFileCache(napi_env env, napi_callback_info info)
304 {
305     NFuncArg funcArg(env, info);
306     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
307         LOGE("Stop Number of arguments unmatched");
308         NError(E_PARAMS).ThrowErr(env);
309         return nullptr;
310     }
311     auto [res, uri] = ParseUriFromParam(env, funcArg);
312     if (res != E_OK) {
313         NError(res).ThrowErr(env);
314         return nullptr;
315     }
316 
317     auto [ret, needClean, maxArgSize] = GetCleanFlagForStop(env, funcArg);
318     if (ret != E_OK) {
319         NError(E_PARAMS).ThrowErr(env);
320         return nullptr;
321     }
322     auto callbackImpl = GetCallbackImpl(env, funcArg, PROGRESS, false);
323     auto cbExec = [uri{uri}, needClean{needClean}, callbackImpl{callbackImpl}]() -> NError {
324         if (callbackImpl == nullptr) {
325             LOGE("Failed to get download callback");
326             return NError(E_PARAMS);
327         }
328         int32_t ret = callbackImpl->StopDownloadInner(uri, needClean);
329         if (ret != E_OK) {
330             LOGE("Stop Download failed! ret = %{public}d", ret);
331             if (ret != E_INVAL_ARG) {
332                 ret = E_BROKEN_IPC;
333             }
334             return NError(Convert2JsErrNum(ret));
335         }
336         return NError(ERRNO_NOERR);
337     };
338 
339     auto cbCompl = [](napi_env env, NError err) -> NVal {
340         if (err) {
341             return {env, err.GetNapiErr(env)};
342         }
343         return NVal::CreateUndefined(env);
344     };
345 
346     string procedureName = "cloudFileCache";
347     auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, maxArgSize);
348     return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbCompl).val_;
349 }
350 
351 struct FileCacheArg {
352     std::vector<std::string> uriList;
353     int64_t downloadId = 0;
354     std::shared_ptr<CloudFileCacheCallbackImplNapi> callbackImpl = nullptr;
355     int32_t fieldKey = FieldKey::FIELDKEY_CONTENT;
356 };
357 
FillParamForBatchStart(napi_env env,NFuncArg & funcArg)358 static std::tuple<int32_t, std::shared_ptr<FileCacheArg>, int32_t> FillParamForBatchStart(napi_env env,
359                                                                                           NFuncArg &funcArg)
360 {
361     size_t maxArgSize = static_cast<size_t>(NARG_CNT::TWO);
362     auto [succ, uriArray, size] = NVal(env, funcArg[NARG_POS::FIRST]).ToStringArray();
363     if (!succ || size == 0) {
364         LOGE("Start get uri array parameter failed!");
365         return {EINVAL, nullptr, maxArgSize};
366     }
367 
368     int32_t fieldKey = 0;
369     if (funcArg.GetArgc() >= NARG_CNT::TWO) {
370         NVal option(env, funcArg[NARG_POS::SECOND]);
371         if (!option.TypeIs(napi_function)) {
372             tie(succ, fieldKey) = option.ToInt32();
373             maxArgSize = static_cast<size_t>(NARG_CNT::THREE);
374         }
375         if (!succ) {
376             LOGE("Failed to get fileType!");
377             return {EINVAL, nullptr, maxArgSize};
378         }
379     }
380 
381     auto fileCache = std::make_shared<FileCacheArg>();
382     fileCache->uriList.swap(uriArray);
383     fileCache->fieldKey = fieldKey;
384     fileCache->callbackImpl = GetCallbackImpl(env, funcArg, MULTI_PROGRESS, true);
385     return {E_OK, fileCache, maxArgSize};
386 }
387 
StartBatchFileCache(napi_env env,napi_callback_info info)388 napi_value CloudFileCacheNapi::StartBatchFileCache(napi_env env, napi_callback_info info)
389 {
390     NFuncArg funcArg(env, info);
391     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
392         LOGE("Start Number of arguments unmatched");
393         NError(EINVAL).ThrowErr(env);
394         return nullptr;
395     }
396 
397     auto [ret, fileCache, maxArgSize] = FillParamForBatchStart(env, funcArg);
398     if (ret != E_OK) {
399         NError(ret).ThrowErr(env);
400         return nullptr;
401     }
402 
403     auto cbExec = [fileCache{fileCache}]() -> NError {
404         if (fileCache == nullptr || fileCache->callbackImpl == nullptr) {
405             LOGE("Failed to get download callback");
406             return NError(JsErrCode::E_INNER_FAILED);
407         }
408         int32_t ret =
409             fileCache->callbackImpl->StartDownloadInner(fileCache->uriList, fileCache->downloadId, fileCache->fieldKey);
410         if (ret != E_OK) {
411             ret = (ret == E_CLOUD_SDK) ? E_SERVICE_INNER_ERROR : ret;
412             return NError(Convert2JsErrNum(ret));
413         }
414         return NError(ERRNO_NOERR);
415     };
416 
417     auto cbCompl = [fileCache{fileCache}](napi_env env, NError err) -> NVal {
418         if (err) {
419             return {env, err.GetNapiErr(env)};
420         }
421         return NVal::CreateInt64(env, fileCache->downloadId);
422     };
423 
424     string procedureName = "cloudFileCache";
425     auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, maxArgSize);
426     return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbCompl).val_;
427 }
428 
StopBatchFileCache(napi_env env,napi_callback_info info)429 napi_value CloudFileCacheNapi::StopBatchFileCache(napi_env env, napi_callback_info info)
430 {
431     NFuncArg funcArg(env, info);
432     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
433         LOGE("Start Number of arguments unmatched");
434         NError(EINVAL).ThrowErr(env);
435         return nullptr;
436     }
437 
438     auto [succ, downloadId] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt64();
439     if (!succ || downloadId <= 0) {
440         LOGE("Start get taskId parameter failed!");
441         NError(EINVAL).ThrowErr(env);
442         return nullptr;
443     }
444 
445     auto [ret, needClean, maxArgSize] = GetCleanFlagForStop(env, funcArg);
446     if (ret != E_OK) {
447         NError(ret).ThrowErr(env);
448         return nullptr;
449     }
450     auto callbackImpl = GetCallbackImpl(env, funcArg, MULTI_PROGRESS, false);
451     auto cbExec = [downloadId{downloadId}, needClean{needClean}, callbackImpl{callbackImpl}]() -> NError {
452         if (callbackImpl == nullptr) {
453             LOGE("Failed to get download callback");
454             return NError(JsErrCode::E_INNER_FAILED);
455         }
456         int32_t ret = callbackImpl->StopDownloadInner(downloadId, needClean);
457         if (ret != E_OK) {
458             ret = (ret == E_CLOUD_SDK) ? E_SERVICE_INNER_ERROR : ret;
459             return NError(Convert2JsErrNum(ret));
460         }
461         return NError(ERRNO_NOERR);
462     };
463 
464     auto cbCompl = [](napi_env env, NError err) -> NVal {
465         if (err) {
466             return {env, err.GetNapiErr(env)};
467         }
468         return NVal::CreateUndefined(env);
469     };
470 
471     string procedureName = "cloudFileCache";
472     auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, maxArgSize);
473     return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbCompl).val_;
474 }
475 
ParseEventFromParam(napi_env env,NFuncArg & funcArg)476 static std::tuple<int32_t, std::string> ParseEventFromParam(napi_env env, NFuncArg &funcArg)
477 {
478     auto [succProgress, progress, size] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
479     if (!succProgress || size == 0) {
480         LOGE("Parase event from parameter failed");
481         NError(EINVAL).ThrowErr(env);
482         return {EINVAL, ""};
483     }
484     string eventType(progress.get());
485     if (eventType == "multiProgress") {
486         eventType = MULTI_PROGRESS;
487     }
488     if ((eventType != PROGRESS && eventType != MULTI_PROGRESS)) {
489         LOGE("Invalid event type!");
490         return {EINVAL, ""};
491     }
492     return {E_OK, eventType};
493 }
494 
On(napi_env env,napi_callback_info info)495 napi_value CloudFileCacheNapi::On(napi_env env, napi_callback_info info)
496 {
497     NFuncArg funcArg(env, info);
498     if (!funcArg.InitArgs(NARG_CNT::TWO)) {
499         LOGE("Batch-On Number of arguments unmatched");
500         NError(EINVAL).ThrowErr(env);
501         return nullptr;
502     }
503     auto [ret, eventType] = ParseEventFromParam(env, funcArg);
504     if (ret != E_OK) {
505         LOGE("On get event type failed!");
506         NError(ret).ThrowErr(env);
507         return nullptr;
508     }
509 
510     if (!NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function)) {
511         LOGE("Batch-On argument type mismatch");
512         NError(EINVAL).ThrowErr(env);
513         return nullptr;
514     }
515 
516     auto callbackImpl = GetCallbackImpl(env, funcArg, eventType, true);
517     if (callbackImpl == nullptr) {
518         LOGE("Failed to init callback");
519         NError(JsErrCode::E_INNER_FAILED).ThrowErr(env);
520         return nullptr;
521     }
522     auto status = callbackImpl->RegisterCallback(funcArg[NARG_POS::SECOND]);
523     if (status != napi_ok) {
524         LOGE("Failed to register callback, status: %{public}d", status);
525         NError(JsErrCode::E_INNER_FAILED).ThrowErr(env);
526         return nullptr;
527     }
528 
529     return NVal::CreateUndefined(env).val_;
530 }
531 
Off(napi_env env,napi_callback_info info)532 napi_value CloudFileCacheNapi::Off(napi_env env, napi_callback_info info)
533 {
534     NFuncArg funcArg(env, info);
535     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
536         LOGE("Off Number of arguments unmatched");
537         NError(EINVAL).ThrowErr(env);
538         return nullptr;
539     }
540     auto [ret, eventType] = ParseEventFromParam(env, funcArg);
541     if (ret != E_OK) {
542         LOGE("Off get event type failed!");
543         NError(ret).ThrowErr(env);
544         return nullptr;
545     }
546 
547     napi_value callbackVel = nullptr;
548     if (funcArg.GetArgc() == (uint)NARG_CNT::TWO) {
549         if (!NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function)) {
550             LOGE("Off argument type mismatch");
551             NError(EINVAL).ThrowErr(env);
552             return nullptr;
553         }
554         callbackVel = funcArg[NARG_POS::SECOND];
555     }
556 
557     auto callbackImpl = GetCallbackImpl(env, funcArg, eventType, false);
558     if (callbackImpl == nullptr || callbackImpl->UnregisterCallback(callbackVel) != napi_ok) {
559         LOGE("Failed to unregister callback, for eventType: %{public}s.", eventType.c_str());
560         NError(JsErrCode::E_INNER_FAILED).ThrowErr(env);
561         return nullptr;
562     }
563 
564     return NVal::CreateUndefined(env).val_;
565 }
566 
GetClassName()567 string CloudFileCacheNapi::GetClassName()
568 {
569     return className_;
570 }
571 } // namespace OHOS::FileManagement::CloudSync